# 读取财报pdf中的财务报表数据表格
import pdfplumber  
import pandas as pd
from collections import OrderedDict 
import csv 

# 银行承兑票据-乐普医疗
# data_bank_piaoju = ['60,631,562.69','68,366,738.81','34,766,157.96','12,351,880.00','33,738,075.21','141,857,631.64',]
# 紫光
# data_bank_piaoju = ['82,980,115.19','195,730,092.92','159,672,777.49','87,334,711.45','86,172,324.23','53,215,497.09',]

# 其他流动资产中金融资产(如金融机构理财产品， 手动填充，只需要数值)
qtld_zz_jinrong = []
# 一年内到期的非流动资产(内含金融资产，如一年内到期的融资租赁款，可以计为金融资产)
ynndq_fld_zz_jinrong = []
# 其他非流动资（内含金融资产，如大额存单、委托贷款）
qtfld_zz_jinrong = []
# 银行承兑票据（只需要数值）
data_bank_piaoju = []

row_xjll_je = []
lirun_titles=[]
lirun_mh_titles=[]

def extract_tables_from_pdf(file_path,page_list,report_type=1):  
    # 合并资产负债表  项目 or 年度/流动资产
    # 合并利润表  项目 or 年度 /一、营业总收入 
    # 合并现金流量表  项目 or 年度/一、经营活动产生的现金流量
    # 
    # report_type = 1负债表，2利润表，3现金流量表，4现金流量补充表
    
    # 每次新表时重置
    # 精确匹配利润表标题
    if report_type == 2:
        lirun_titles[:] = ['其中：营业收入','其中：营业成本','销售费用','管理费用','研发费用','财务费用'] 
        # 模糊匹配利润表标题
        lirun_mh_titles[:] = ['税金及附加','利息费用','利息收入','其他收益','联营企业','投资收益',
                          '公允价值变动收益','资产处置收益','营业利润','利润总额','所得税费用','归属于母公司','少数股东损益','净利润']
    
    with pdfplumber.open(file_path) as pdf:  
        # 遍历PDF中的每一页  
        # for page in pdf.pages:  
        #     # 提取当前页的所有表格  
        #     tables = page.extract_tables()  
        #     if len(tables)>0:
        #         print("page:",print(page.page_number))
        #         print("tables:",len(tables))
        #     for table in tables:  
        #         for row in table:  
        #             print(row)  
        #         print()  # 在每个表格之间打印一个空行以便区分  
        # # 确实能打印出表格数据
        print("pages:",len(pdf.pages))

        # 读取指定页面的表格：
        all_rows = []
        header_title = []
        header_indices = []
        last_values = [] #一行数据分成双行，标题和数据行分开，记录是先出现的标题，还是先出现的值
        r_start = page_list.start
        r_stop = page_list.stop+1
        page_list = range(r_start,r_stop)
        
        for page_number in page_list:
            page = pdf.pages[page_number-1]
            tables = page.extract_tables()
            if len(tables)==0:
                print("find.null.table:",page_number)
                continue
            if page_number == page_list[0] and page_number == page_list[-1]:
                # 现金补充表通常在一个页面表中取完
               y_table = tables #有可能是第1个表、第2表、第3表中，只能逐个寻找了 
            elif page_number == page_list[0]:
                y_table = [tables[len(tables)-1]]
            elif page_number == page_list[-1]:
                y_table = [tables[0]]
            else:
                y_table = tables

            # 遍历并打印所有表格
            next_header = [] #用于判断同一个负债表，不同page下标题是否重复显示了
            for table_idx, table in enumerate(y_table):
                print(f"Page {page_number + 1}, Table {table_idx + 1}:")  
                # all_list = []
                for row in table:  
                    print(row)
                # 提取并打印数据行  table[0]=['项目', '2019年12月31日', '2018年12月31日'],table[1]=['流动资产：', '', '']

                # sb的盈趣科技不但数据行格式杂乱无章，现金表2023的标题行格式也不对，尼玛！
                # ['', '2023年度', '']
                # ['项目', None, '2022年度'] 
                next_header = extract_data_title(table[0])
                next_table = table[1:]
                if len(all_rows)==0:
                    header_title = next_header
                    if len(header_title)<3:
                        if len(table[0]) == 3:
                            header_title = ['项目','期末','期初']
                    if len(header_title)<3:
                        #没有任何数据的情况下，还没找到标头，则说明此表非期望表(现金补充表会有此情况)
                        print("--err.table_idx:",table_idx)
                        continue
                    header_title[0] = header_title[0].replace(' ','')
                    all_rows.append(header_title)
                    print("--title:",header_title)
                    header_indices = extract_data_title_index(table[0],header_title)
                    if len(header_indices)<3:
                            header_indices = [0,len(table[0])-2,len(table[0])-1]
                    
                else:
                    #下一个表格是否仍旧有标题头
                    if len(next_header)>0 and next_header[0] == header_title[0]:
                        print("cancel.非首个表格也有标题头")
                        next_table = table[1:] #从第2行开始为数据
                    else:
                        next_table = table[0:] #否则第一行就是数据了

                #第2行以下即为数据行，根据数据行格式找到数据所在index
                rows_indices = extract_data_row_index(header_indices,next_table)
                # 同一个表格内的index一样，但是不同的表格，其index是不一样的，所以不同的table开始时，需要重新定计算内容index
                # 后面发现利润表同一个表格内的index也不一样，如
                # ['', '减：所得税费用', '', '44,778,944.72', '27,194,950.89']  >rows_indices=[1,3,4]
                # ['五、净利润（净亏损以“－”号填列）', None, None, '330,325,450.64', '254,799,474.65'] >rows_indices=[0,3,4]
                # 所以得到值为[None,'330,325,450.64', '254,799,474.65'],第1个值为None，后面2个是有值的
                # 此种情况，分析时，要再判断一下在next_table[next_table]的rows_indices
                print("--content.indices:",rows_indices)
                print('\n')
                if len(rows_indices) == 0:
                    rows_indices = header_indices
                
                rows_datas = [[cell for i, cell in enumerate(row) if i in rows_indices] for row in next_table]
                biyouTitle = query_IfRight_rowindex(rows_datas,report_type)
                if len(biyouTitle)>0:
                    retry_indices = find_ok_value_index(next_table,biyouTitle,header_indices)
                    print("+++repair.content.indices:",retry_indices)
                    rows_datas = [[cell for i, cell in enumerate(row) if i in retry_indices] for row in next_table]
                    
                for index,row in enumerate(rows_datas):
                    row_title = row[0] if row[0] is None else row[0].replace('\n','').strip()
                    # 判断如是标题行,则舍弃
                    if row_title is not None and (row_title == '项目' or '补充' in row_title or query_title_in_lines(row[1:])):                        
                        if 4==report_type and '补充' in row_title and 1==len(all_rows):
                            # 说上一个表格的标题有误，校正
                            all_rows[0] = row
                        print('cancel.title.row:',row)
                        continue # 是标题栏则不用处理
                    #标题里还有\n的情况,也有None的情况，所以不能直接用row[0].strip()
                    has_ok_value =  query_any_value_in_line(row[1:])
                    
                    if (row_title is not None) and len(row_title)>0:
                        last_values.append(row) #先有标题
                    elif has_ok_value: #没标题但有值
                        print('-------title.is.none & have.data:',row)
                        if len(next_table[index])>3: #如果原列数超过3列则重新校验获取标题
                            data_2 = reget_rowd_datas(len(header_title),next_table[index],row)
                            if len(data_2)>0:
                                row_title = data_2[0] if data_2[0] is None else data_2[0].replace('\n','').strip() 
                                #判断是否Over有用
                            if len(data_2)==len(header_title): #校正获取到了标题
                                last_values.append(data_2)
                            else: #仍无标题，纯值行
                                last_values.append(row)
                        elif 3 == len(next_table[index]):
                            #如果原数据本身就3列，说明就是有值但无标题的行
                            print('-------title.is.none & have.data,but len<=3:',next_table[index])
                            last_values.append(row)
                    else:
                        # 无标题无值，则直接pass
                        print('cancel.全空或None行.clear')
                        last_values.clear()
                        continue
                            
                    ok_row_data = get_right_row_data(last_values,report_type,len(all_rows))
                    if len(ok_row_data) == len(header_title):
                        # 所有者权益（或股东权益）合计\所有者权益(或股东权益)合计、所有者权益（或股东权益）合 计
                        # 负债合 计、非流动负债合 计、非流动资产合 计、流动资产合 计
                        if 1==report_type:
                            if ok_row_data[0] == '应付票据及应付账款':
                                ok_row_data[0] = '应付账款'
                            elif ok_row_data[0] == '其中：应收票据':
                                ok_row_data[0] = '应收票据'
                            elif ok_row_data[0].startswith('归属于母公司'): #and '所有者' in ok_row_data[0]
                                ok_row_data[0] = '归母权益合计'
                            elif ok_row_data[0].startswith('所有者权益') : #and  '或股东权益' in ok_row_data[0]
                                ok_row_data[0] = '所有者权益合计'
                            elif ok_row_data[0].startswith('以公允价值计量'):
                                # 中顺洁柔/海康是坑爹的’以公允价值计量且其变动计入当‘
                                if '金融资产' in ok_row_data[0]:
                                    ok_row_data[0] = '以公允价值计量且其变动计入当期损益的金融资产'
                                elif '金融负债' in ok_row_data[0]:
                                    ok_row_data[0] = '以公允价值计量且其变动计入当期损益的金融负债'
                                elif len(all_rows)<7:
                                    ok_row_data[0] = '以公允价值计量且其变动计入当期损益的金融资产'
                                else:
                                    ok_row_data[0] = '以公允价值计量且其变动计入当期损益的金融负债'
                            elif '股本'==ok_row_data[0] or ok_row_data[0].startswith('实收资本'):
                                ok_row_data[0] = '股本'
                        elif 3==report_type:
                            if ok_row_data[0]=='取得子公司':
                                if all_rows[-1][0]=='处置子公司': #正确应该在’购建固定资产‘之后
                                    # 潍柴居然在投资流入>处置子公司下还有个'取得子公司及其他营业单位收到的现金净额'的记录，操蛋
                                    print("---cancel:",ok_row_data)
                                    continue;
                        ok_row_data[0] = ok_row_data[0].replace(' ','')
                        all_rows.append(ok_row_data)
                        print("---add.ok.row:",all_rows[-1])
                        last_values.clear()
                        if 2 == report_type:
                            if all_rows[-2][0] == '归母净利润' or all_rows[-1][0] == '少数股东损益': #归母后面再读取一个少数股东权益
                                print("----over.利润表:")
                                print_row_data(all_rows)
                                print("读取利润财报数据完毕:",len(all_rows))
                                return all_rows
                            
                    if row_title is not None and len(row_title)>0:
                        # 分配股利、利润或偿付利息支付的现金，筹资活动现金流出小计，筹资活动产生的现金流量净额
                        if 3 == report_type and (row_title.startswith('筹资活动现金流出') or row_title.startswith('筹资活动产生的现金流')):
                            print("----over.现金表")
                            print_row_data(all_rows)
                            print("读取现金财报数据完毕:",len(all_rows))
                            return all_rows
                        elif 1 == report_type and row_title.startswith('负债和所有者权益'):
                            # '负债和所有者权益（或股东权益）总计',有标题为’负债和所有者权益（或‘的情况
                            print("-----over:负债表")
                            all_rows[-1][0]='负债和所有者权益（或股东权益）总计';
                            print_row_data(all_rows)
                            print("读取负债财报数据完毕:",len(all_rows))
                            return all_rows
                        elif 4 == report_type and '处置固定资产' in row_title:
                            print("----over.现金补充表")
                            print_row_data(all_rows)
                            print("读取现金补充数据完毕:",len(all_rows))
                            return all_rows

        print_row_data(all_rows)
        print("读取财报数据完毕:",len(all_rows))
        return all_rows
    
def get_right_row_data(row_data,report_type,ok_count):
    row = []
    if len(row_data)>=2:
        # [['流动资产：', '', ''], ['货币资金', '635,185,708.80', '1,083,215,309.00']]
        row_1 = row_data[-1]
        row_2 = row_data[-2]
        # 优先判断最后一个是否有标题且有值，如果正常的，则直接得到该行，并清除
        if query_chineses_in_line(row_1[0]):
            has_value = query_any_value_in_line(row_1[1:])
            if has_value:
                row = row_1
                row_data.clear()
            else:
                row = [row_1[0]] + row_2[1:]
                if query_any_value_in_line(row_2[1:]):
                    print("--合成有效数据：",row)
                    row_data.clear()
                else:
                    row_data[:] = [row_data[-1]]
        elif query_chineses_in_line(row_2[0]):
            row = [row_2[0]] + row_1[1:]
        else:#两行都没有标题
            if query_any_value_in_line(row_data[-1]): #如果最后一行有值，则保留
                row_data[:] = [row_data[-1]]
            else: #否则全部舍弃
                row_data.clear()
            # ['', None, ''] 或 ['', '780,403,040.00', '']
            # ['', '780,403,040.00', '782,789,273.00']
            # 前后两行是这种的情况，保留最后一行和下一个结合? 基本不可能有这种情况，暂不考虑
            return []
    else:
        row = row_data[-1]
        if query_chineses_in_line(row[0]) and query_any_value_in_line(row[1:]):
           row_data.clear()
        
    if len(row) == 3:
        row_title = row[0] if row[0] is None else row[0].replace('\n','').strip()
        has_value = query_any_value_in_line(row[1:])
        if has_value and query_chineses_in_line(row_title):
            # 有效行
            if 1 == report_type:
                return [row_title] + row[1:]
            elif 2 == report_type:
                lirun_title = is_in_lirun_titls(row_title,ok_count>=5)
                if len(lirun_title)>0:
                    return [lirun_title] + row[1:]
                else:
                    print('cancel.lirun:',row)
                    row_data.clear()
            elif 3 == report_type:
                xianjin_title = is_in_xianjin_titles(row_title)
                if len(xianjin_title)>0:
                    return [xianjin_title] + row[1:]
                else:
                    print('cancel.xianjin:',row)
                    row_data.clear()
            elif 4 == report_type:
                xianjin_buchong_title = is_in_xianjinbuchong_titles(row_title)
                if len(xianjin_buchong_title)>0:
                    return [xianjin_buchong_title] + row[1:]
                else:
                    print('cancel.xianjinbuchong:',row)
                    row_data.clear()
                       
    return []    

def is_in_lirun_titls(title,mh_flag=False):
    if title in lirun_titles:
        if title == '其中：营业收入':
            lirun_titles.remove('其中：营业收入')
            return '营业收入'
        elif title == '其中：营业成本':
            lirun_titles.remove('其中：营业成本')
            return '营业成本'
        else:
            lirun_titles.remove(title)
            return title
    elif title == '一、营业收入': #京沪高铁2019利润表特殊
        lirun_titles.remove('其中：营业收入')       
        return '营业收入'
    elif title == '减：营业成本': #京沪高铁2019利润表特殊
        lirun_titles.remove('其中：营业成本')
        return '营业成本'
    elif mh_flag:
        # 注意'联营企业'要在'投资收益'之前，因为除了'投资收益（损失以“－”号填列）之外，'其中：对联营企业和合营企业的投资收益'也会命中'投资收益'
        target = [item for item in lirun_mh_titles if item in title]
        if len(target)>0:
            if target[0] == '联营企业':
                lirun_mh_titles.remove('联营企业')
                return '长期股权投资收益'
            elif target[0] == '归属于母公司': #1.归属于母公司股东的净利润
                lirun_mh_titles.remove('归属于母公司')
                return '归母净利润'
            else:
                lirun_mh_titles.remove(target[0])
                return target[0]
    return ''
def is_in_xianjin_titles(title):
    xianjin_titles = ['经营活动产生的现金流量净额','处置固定资产','处置子公司','购建固定资产','取得子公司','分配股利']
    target = [item for item in xianjin_titles if title.lstrip().startswith(item)]
    if len(target)>0:
        return target[0]
    elif title.lstrip().startswith('销售商品') and '提供劳务' in title: #'销售商品、提供劳务收到的现金',
        return '销售商品收到的现金'
    else:
        return ''
def is_in_xianjinbuchong_titles(title):
    xianjin_buchong_start = ['固定资产折旧','使用权资产','无形资产','长期待摊'] #'固定资产折旧',存在‘固定资产、投资性房地产及使用权资产折旧’
    target = [item for item in xianjin_buchong_start if title.lstrip().startswith(item)]
    if len(target)>0:
        oktitle = target[0]
        if oktitle == '使用权资产' or oktitle == '无形资产':
            oktitle = oktitle + '折旧'
        elif oktitle == '长期待摊':
            oktitle = '长期待摊费用摊销'
        return oktitle
    elif title.lstrip().startswith('固定资产') and title.lstrip().endswith('折旧'):
        return '固定资产折旧'
    elif title.rstrip().endswith('资产减值准备'):
        return '资产减值准备'
    elif title.rstrip().startswith('信用减值'): #信用减值损失
        return '信用减值损失'
    else:
        return ''
    
def save_data_2_number(all_rows,filepath):
    # 将数据保存到表格文件
    # 如果列表的第一行是表头，则不需要指定columns参数  
    title_row_count = len(all_rows[0])
    
    for index,row in enumerate(all_rows):
        if len(row)>title_row_count:
            print("err.row:",row)
            all_rows[index] = row[:title_row_count]

    df = pd.DataFrame(all_rows[1:], columns=all_rows[0])  # 跳过表头行，使用表头作为列名  
    # # 将DataFrame保存为CSV文件  
    df.to_csv(filepath, index=False)  # index=False表示不保存行索引
    # # 保存为Excel文件  
    # # df.to_excel('海康_合并负债表.xlsx', index=False) #需pip install openpyxl或pip install xlwt xlsxwriter
    print("保存表格数据完毕:",filepath)
           
def extract_data_title(header_row):
    result = [cell for cell in header_row if cell!='' and cell is not None]
    if len(result)>3:
        if '附注' in result:
            result.remove('附注')
        if len(result)>3: #删除后还大于3，说明有多余的年份数据
            if ('年' in result[1] and '月' in result[2]) or ('本年' in result[1] and '上年' in result[2]) or ('年度' in result[1] and '年度' in result[2]) or ('期末' in result[1] and '期初' in result[2]) or ('本期' in result[1] and '上期' in result[2]):
                result = [result[0],result[1],result[2]]
        if len(result)>3:
            result = [result[0],result[-2],result[-1]]
    if len(result)==3:
        if ('年' in result[1] and '月' in result[2]) or ('本年' in result[1] and '上年' in result[2]) or ('年度' in result[1] and '年度' in result[2]) or ('期末' in result[1] and '期初' in result[2]) or ('本期' in result[1] and '上期' in result[2]):
            return result
        else:
            return "" #错误的标题头
    return result
# and ('项目' in cell or '年' in cell or '月' in cell or '日' in cell)
def extract_data_title_index(header_row,header_title):
    result = [i for i, cell in enumerate(header_row) if cell in header_title]
    if len(result)>3:#if '年' in result[1]:
        if '年' in header_title[1] or '期末' in header_title[1] or '本期' in header_title[1]:
            result = [result[0],result[1],result[2]]
        else:
            result = [result[0],result[-2],result[-1]]
    return result

# 参考标题得到有值的row_index,
def extract_data_row_index(header_indices,data_rows):
    row_indexs = []
    header_col_count = len(header_indices)
    for row_data in data_rows:
        data = [cell for cell in row_data if cell!='' and cell is not None]
        # 写错了，还有这种情况:['一年内到期的非流动负债', '附注七、43', '640,768.82', ''],有值的列只有一个数据，这样取会取到附注列上去
        if len(data) >= header_col_count:
            # 必须要判断一下有没有附注的情况
            has_title = False
            for index,coltitle in enumerate(data):
                col_title = coltitle.strip()
                if col_title.startswith('附注'):#有可能没有附注2字，只是如：七、（一）
                    del data[index]
                elif query_chineses_in_line(col_title):
                    if has_title: #已经有title了，又出现汉字的，则也为附注
                        del data[index]
                    has_title = True
                elif len(col_title)<=3: #还有一种 注释列只有序号：['信用减值损失（损失以“-”\n号填列）', '9', '-6,262,245.03', '']
                    # 序号最多3位数
                    del data[index]
            if len(data) >= header_col_count:                
                # 依次判断row,得到cell，且cell的个数与header_title的个数相同，说明此行可以得到正确的rowinddex
                row_indexs = [i for i, cell in enumerate(row_data) if cell in data]
                break
            
    if len(row_indexs)> header_col_count:
        if header_indices == row_indexs[:len(header_indices)]: 
            return header_indices
            #如果row_indexs包含header_indices，则说明数据位置正确，只是多了，直接取header_indices的位置即可
        else:
            return [row_indexs[0],row_indexs[-2],row_indexs[-1]]
    return row_indexs

def query_IfRight_rowindex(rows_datas,report_type):
    #extract_data_row_index还有可能前几行用rows_indices能取到数据，后几行用rows_indices取不到数据，此时需要重新校正rows_indices
    # 所以此处再做判断，如果得到的rows_datas中，有一项的标题是必有值项的标题，结果却没有值，
    # 则说明rows_indices有误，需根据此必有项标题从next_table中重新取到rows_indices
    # rows_datas = [['xxx','0','0'],['xxx','0','0']...]
    biyouTitle_1 = ['货币资金','应收账款','其他应收款','其他流动资产','固定资产','在建工程','长期待摊费用','应付账款','应付职工薪酬','股本','实收资本（或股本）','未分配利润']
    # '存货',三七互娱存货为0
    biyouTitle_2= ['营业总收入','营业收入','营业总成本','营业成本','销售费用','管理费用','研发费用','财务费用','营业利润','利润总额','持续经营净利润','归属于母公司股东的净利润']
    biyouTitle_3=['销售商品','经营活动产生的现金流量净额','提供劳务收到的现金','购买商品','接受劳务支付的现金','购建固定资产']
    biyouTitle_4=['固定资产折旧','长期待摊'] #'资产减值准备',
    for index,row in enumerate(rows_datas):
        row_title = row[0] if row[0] is None else row[0].replace('\n','').strip()
        if row_title is not None:
            if 1==report_type:
                if row_title in biyouTitle_1:
                    if row[1] is not None and '.' in row[1] and ',' in row[1] and row[2] is not None and '.' in row[2] and ',' in row[2]:
                        return ''
                    else:
                        return row[0] #返回没有值的这项，需要重新取index
            elif 2==report_type:
                hastitle = any(item in row_title for item in biyouTitle_2)
                if hastitle:
                    if row[1] is not None and '.' in row[1] and ',' in row[1] and row[2] is not None and '.' in row[2] and ',' in row[2]:
                        return ''
                    else:
                        return row[0]
            elif 3==report_type:
                hastitle = any(item in row_title for item in biyouTitle_3)
                if hastitle:
                    if row[1] is not None and '.' in row[1] and ',' in row[1] and row[2] is not None and '.' in row[2] and ',' in row[2]:
                        return ''
                    else:
                        return row[0]
            elif 4==report_type:
                hastitle = any(item in row_title for item in biyouTitle_4)
                if hastitle:
                    if row[1] is not None and '.' in row[1] and ',' in row[1] and row[2] is not None and '.' in row[2] and ',' in row[2]:
                        return ''
                    else:
                        return row[0]
    return ''

def find_ok_value_index(next_table,rowtitle,rows_indices):
    result = next((sub_array for sub_array in next_table for element in sub_array if element == rowtitle), None)
    if result:
        # data = [cell for cell in result if cell!='' and cell is not None]
        i_1=-1
        i_2=0
        i_3=0
        for index,coltitle in enumerate(result):
            if coltitle!='' and coltitle is not None:
                if coltitle==rowtitle:
                    i_1 = index
                elif i_2>0 and coltitle is not None and ',' in coltitle and '.' in coltitle and not query_chineses_in_line(coltitle) :
                    i_3=index
                    break
                elif i_1>=0 and i_2==0 and coltitle is not None and ',' in coltitle and '.' in coltitle and not query_chineses_in_line(coltitle) :
                    i_2=index
        if i_1 < i_2 and i_2 < i_3:  
            return [i_1,i_2,i_3]
    
    return rows_indices


import re
 # 获取字符串中的汉字串(汉字包括 一、二)
def query_chineses_in_line(line):
    if line is None:
        return False
    return re.findall(r'[\u4e00-\u9fa5]+', line)
def query_any_value_in_line(lines):
    if lines is None:
        return False
    return any(('' != item and item is not None) for item in lines)
def query_title_in_lines(lines):
    if lines is None:
        return False
    for line in lines:
        if query_chineses_in_line(line):
            return True
    return False
# 参考标题个数重新询问该行的值,
def reget_rowd_datas(header_col_count,row_data,err_row):
    #还有这2种情况: 
    # 首个为None(或者为空)，但其实有值的，说明可能是前面取的index不对，则对此行数据，重新取一下
    # index = [0,3,4]
    # 原row =['', '投资收益（损失以“－”号填', '', '-126,867,732.81', '-75,714,858.16'] 
    # 取值 = ['', '-126,867,732.81', '-75,714,858.16'] 
    # 原row =[None, '投资收益（损失以“－”号填', '', '-126,867,732.81', '-75,714,858.16'] 
    # 取值 = [None, '-126,867,732.81', '-75,714,858.16'] 
    # 还有一种是，第1值为空，但后面有值['', '780,403,040.00', '782,789,273.00']，而且原row中确实没有标题，
    # 这种情况是负债表中某个项目的值行，标题在下一行
    data = [cell for cell in row_data if cell!='' and cell is not None]
    if len(data) >= header_col_count:
        if '附注' in data:
            data.remove('附注')
        else:
            # 必须要判断一下有没有附注的情况
            has_title = False
            for index,coltitle in enumerate(data):
                col_title = coltitle.strip()
                if col_title.startswith('附注'):
                    del data[index]
                elif query_chineses_in_line(col_title):
                    if has_title:
                        del data[index]
                    has_title = True
                    
        if len(data) == header_col_count:
            return data
    else:
        # 还有row_data=['', '公允价值变动收益（损失以', '', '-38,772.51', '']的情况
        # 虽然重新取得了title，但因为只有一个年份有值，结果：
        # 取得的值为：['公允价值变动收益（损失以', '-38,772.51']
        # 这个时候直接用title+err_row[1:]
        # 同时还有[None, '-40,654,249.62', '-43,963,588.26']这种情况，得到data=['-40,654,249.62', '-43,963,588.26']
        # 此时再 [data[0]] + err_row[1:]，则也会错误
        # 还有一种情况数据行['', '780,403,040.00', '782,789,273.00']，标题在下一行或上一行中，此时取得的就是2个数据，但data[0]不是汉字标题
        if query_chineses_in_line(data[0]):
            data = [data[0]] + err_row[1:]
        else:
            return data
    return []
 


def combine_2_data(list1,list2):
    if not list1 or len(list1)==0 or not list2 or len(list2)==0:
        print("error.data!!!")
        return
    # if abs(len(list1)-len(list2))>40:
    #     print("error.data.len!!!")
    #     return
    # 创建一个字典来存储数据，键是标题，值是列表（包含对应的数据）  
    merged_data = {}  
    merged_list = []

    # 遍历list1并填充字典  
    value_col_1 = len(list1[0])-1 #list1不存在时要填充的value个数
    value_col_2 = len(list2[0])-1
    list_of_empty_1 = ['' for _ in range(value_col_1)] #填充list1表用
    list_of_empty_2 = ['' for _ in range(value_col_2)] #填充list2表用

    for sublist in list1:  
        title = sublist[0]
        if title in merged_data:
            print("cancel.repeat:",title)
        else:
            merged_data[title] = sublist[1:]  # 去掉list1重复项
            if len(merged_data[title])>value_col_1:
                print(f"title:{title},err.len.value:{merged_data[title]}")
        # merged_list.append([title,sublist[1:]])

    merged_list = [[key, value] for key, value in merged_data.items()]

    # 遍历list2并更新字典或添加新条目(如果没有添加过的，则插入新标题，并补充list1的默认空值)
    for index,sublist in enumerate(list2):  
        title = sublist[0]
        # 利用字典表(merged_data)的key的唯一性，来进行相同的标题的则拼接; 不存在的key，则新增，然后插入到列表
        if title in merged_data:
            for ilist,item in enumerate(merged_list): 
                if item[0] == title: #在list_1中查找，因为有重复的子项(如应收股利)，所以除了验证标题之外，还要对应项的位置相差不大
                    # if abs(index-ilist)<4:
                    merged_data[title] += sublist[1:]
                    merged_list[ilist] = [title,merged_data[title]] #更新列表
                    if len(merged_data[title])>value_col_1+value_col_2:
                        print(f"---title:{title},err.len.value:{merged_data[title]}")
                    # else:
                        # print(f"---cancel: index({index})-ilist({ilist}):{title}")
                    if abs(index-ilist)>10:
                        print(f"---waring: index({index})-ilist({ilist}):{title}")
                    break
                    
        else:   
            merged_data[title] = list_of_empty_1 + sublist[1:]  #第2个列表中有，但第一个列表没有的，则插入一个新项，并且将第1个列表的值置为空
            if len(merged_data[title])>value_col_1+value_col_2:
                print(f"title:{title},err.len.value:{merged_data[title]}")
            if (index+1>len(merged_list)):
                merged_list.append([title,merged_data[title]])
            else:
                merged_list.insert(index+1,[title,merged_data[title]]) #插入列表
    # 以上完成list2存在，list1不存在的标题，并做了填充；
    # 但还有可能lis1存在，list2不存在的标题，虽list1已添加到新列表，则没有填充值
    #转换列表为想要的格式
    print('\n')
    
    result_list = []
    for row in merged_list: 
        if len(row[1])<value_col_1+value_col_2: #说明list1存在，而list2不存的，没有填充（其实可以不需要，保存至表格时会自动填充空）
            new_row = [row[0]] + row[1] + list_of_empty_2
            if len(new_row)>value_col_1+value_col_2+1:
                print(f"err.len.value:{new_row}")
        else:
            new_row = [row[0]] + row[1]
            if len(new_row)>value_col_1+value_col_2+1:
                print(f"err.len.value:{new_row}")
        result_list.append(new_row)
        print(new_row)
        
    return result_list


def get_fuzai_report(files,ranges):
    # 获取近6年的合并负债表数据
    data_2023 = extract_tables_from_pdf(files[0],ranges[0])
    if len(files)>1 and data_2023 is not None and len(data_2023)>0:
        data_2021 = extract_tables_from_pdf(files[1],ranges[1])
        result_2 = combine_2_data(data_2023,data_2021)
        if len(files)>2 and data_2021 is not None and len(data_2021)>0:
            data_2019 = extract_tables_from_pdf(files[2],ranges[2])
            return combine_2_data(result_2,data_2019)
        else:
            return result_2
    else:
        return data_2023
def get_lirun_report(files,ranges):
    # 获取近6年的合并利润表数据
    data_2023 = extract_tables_from_pdf(files[0],ranges[0],2)
    if len(files)>1:
        data_2021 = extract_tables_from_pdf(files[1],ranges[1],2)
        result_2 = combine_2_data(data_2023,data_2021)
        if len(files)>2:
            data_2019 = extract_tables_from_pdf(files[2],ranges[2],2)
            return combine_2_data(result_2,data_2019)
        else:
            return result_2
    else:
        return data_2023
def get_xianjin_report(files,ranges):
    # 获取近6年的合并现金流量表数据
    data_2023 = extract_tables_from_pdf(files[0],ranges[0],3)
    if len(files)>1:
        data_2021 = extract_tables_from_pdf(files[1],ranges[1],3)
        result_2 = combine_2_data(data_2023,data_2021)
        if len(files)>2:
            data_2019 = extract_tables_from_pdf(files[2],ranges[2],3)
            return combine_2_data(result_2,data_2019)
        else:
            return result_2
    else:
        return data_2023
    
def get_xianjin_buchong_report(files,ranges):
    # 获取近6年的合并现金流量表数据
    if len(ranges)<3:
        return []
    data_2023 = extract_tables_from_pdf(files[0],ranges[0],4)
    if len(files)>1:
        data_2021 = extract_tables_from_pdf(files[1],ranges[1],4)
        result_2 = combine_2_data(data_2023,data_2021)
        if len(files)>2:
            data_2019 = extract_tables_from_pdf(files[2],ranges[2],4)
            return combine_2_data(result_2,data_2019)
        else:
            return result_2
    else:
        return data_2023

def read_data_from_csv(filepath):
    # 打开CSV文件 
    print('\nreadfrom:',filepath)
    data = []
    try:
        with open(filepath, mode='r', newline='') as file:  
            reader = csv.reader(file)  
            # 读取CSV文件的所有行，并存储到列表中  
            data = list(reader)  
            # 打印数据  
            print_row_data(data)
    except:
        print("readfile.err")
    finally:
        return data

def print_row_data(data):
    for row_data in data:
        print(row_data)

def repair_nulldata_2_zero(list_data):
        # 将空值改为0,只去空值，
        return [item if (item and '-' != item and '—' != item and '--' not in item and '—-' not in item) else '0.0' for item in list_data]
def get_list_data_sum(list1,list2):
    # 使用zip函数将两个列表的对应元素打包成元组，并使用列表推导式进行相加  
    result = [float(x) + float(y) for x, y in zip(list1, list2)]
    return result
def get_list_data_subtract(list1,list2):
    # 使用zip函数将两个列表的对应元素打包成元组，并使用列表推导式进行相减 
    result = [float(x) - float(y) for x, y in zip(list1, list2)]
    return result
# 去掉列表中的每行列表的每个元素的千分位分隔符
def remove_mutilist_data_douao(value_list):
    # for row_value in value_list:
        # row_value = remove_list_data_douao(row_value) 
        #这样并不会同步修改value_list原值，而只是修改了row_value
    for i in range(0, len(value_list)):   
        value_list[i] = remove_list_data_douao(value_list[i]) #这样才行
        #或者这样
        # for row_value in value_list
        #   for i in range(0, len(row_value)): 
        #     # 去掉千分位分隔符
        #     row_value[i] = row_value[i].replace(',', '') #replace会影响列表原值，只要是非赋值类型的操作，都会影响原始值
# 去掉单个列表的元素的千分位分隔符            
def remove_list_data_douao(value_list):
    value_list = repair_nulldata_2_zero(value_list) #先去空值等非有效数值，再去掉,变成数值类型
    for i in range(0, len(value_list)): 
        # 去掉千分位分隔符及左右括号#老百姓利润表还有数据为(48,131,720)
        value_list[i] = value_list[i].replace(',', '').replace('(', '').replace('（', '').replace(')', '').replace('）', '')
    return value_list
# 获取有息负债列表及总额
def get_youxifuzai_data(old_list,sum_youxi):
    row_youxi_titles = ['短期借款','长期借款','应付债券','一年内到期的非流动负债','租赁负债','交易性金融负债','衍生金融负债']
    youxi_list = []
    for title in row_youxi_titles:
        youxi_row = [row for row in old_list if row[0] == title]
        if len(youxi_row)>0:
            row_data = youxi_row[0]
            # 判断该行是否有值，如果没有值则没必要显示
            if any('' != item for item in row_data[1:]):
                youxi_list.append(repair_nulldata_2_zero(row_data))
            else:
                print("cancel.全空数据:",row_data)
        else:
            print("not.find:",title)
    # 以公允价值计量且其变动计入当期损益的金融负债
    youxi_row = [row for row in old_list if '计入当期损益的金融负债' in row[0]]
    if len(youxi_row)>0:
        row_data = youxi_row[0]
        # 判断该行是否有值，如果没有值则没必要显示
        if any('' != item for item in row_data[1:]):
            row_data[0]= '计入当期损益的金融负债'
            youxi_list.append(repair_nulldata_2_zero(row_data))
        else:
            print("cancel.全空数据:",row_data)
    else:
        print("not.find:",title)
    
    youxi_value = [item[1:] for item in youxi_list] #取各行数据列
    remove_mutilist_data_douao(youxi_value)
    # 计算得到有息负债总额：
    tmp_value = sum_youxi
    for row_data in youxi_value:
        tmp_value = get_list_data_sum(tmp_value,row_data) 
        #重新赋值列表参数，并不能改变列表参数原值，只是赋值了一个新对象
    sum_youxi[:] = tmp_value #须使用切片，以改变参数原值
    # 计算好的总额，还原成千分位分隔，且保留两位小数位  
    formatted_youxi=["{:,.2f}".format(num) for num in sum_youxi]
    formatted_youxi.insert(0,"∑有息负债总额")
    youxi_list.append(formatted_youxi)
    #新增有息负债
    value_yxfz_grow = calc_growing_value(sum_youxi)
    formatted_yxfz_add=["{:,.2f}".format(num) for num in value_yxfz_grow]
    youxi_list.append(['有息负债增长净额']+formatted_yxfz_add)
    return youxi_list

# 获取金融资产列表及总额
def get_jinrong_data(old_list):
    i_title_col = len(old_list[0])
    row_jinrong_titles = ['货币资金','拆出资金','交易性金融资产','衍生金融资产','持有待售资产','可供出售金融资产','债权投资','其他债权投资',
                          '其他权益工具投资','其他非流动金融资产','买入返售金融资产','持有至到期投资','其他流动资产-金融资产',
                          '其中：应收利息','应收股利']
    jinrong_list = []
    for title in row_jinrong_titles:
        youxi_row = [row for row in old_list if row[0] == title]
        if len(youxi_row)>0:
            row_data = youxi_row[0]
            if any('' != item for item in row_data[1:]):
                jinrong_list.append(repair_nulldata_2_zero(row_data))
            else:
                print("---cancel.全空金融项目数据:",row_data)
        else:
            print("---not.find.金融项目:",title)
        
    # 以公允价值计量且其变动计入当期损益的金融资产,中顺洁柔是坑爹的’以公允价值计量且其变动计入当‘
    youxi_row = [row for index,row in enumerate(old_list) if ('计入当期损益的金融资产' in row[0] or '以公允价值计量' in row[0]) and index<7]
    if len(youxi_row)>0:
        row_data = youxi_row[0]
        if any('' != item for item in row_data[1:]):
            row_data[0] = '计入当期损益的金融资产'
            jinrong_list.append(repair_nulldata_2_zero(row_data))
        else:
            print("---cancel.全空金融项目数据:",row_data)
    else:
        print("---not.find.金融项目:",title)
     
    if len(qtld_zz_jinrong) == i_title_col-1:
        jinrong_list.append(['其他流动资产-金融资产']+repair_nulldata_2_zero(qtld_zz_jinrong))
    if len(qtfld_zz_jinrong) == i_title_col -1:
        jinrong_list.append(['其他非流动资产-金融资产']+repair_nulldata_2_zero(qtfld_zz_jinrong))
    if len(ynndq_fld_zz_jinrong) == i_title_col -1:
        jinrong_list.append(['一年内到期非流动资产-金融资产']+repair_nulldata_2_zero(ynndq_fld_zz_jinrong))  

    # if len(data_bank_piaoju) == i_title_col-1:
    #     copy_list = data_bank_piaoju[:]
    #     jinrong_list.append(['银行承兑票据']+repair_nulldata_2_zero(copy_list))
                    
    jinrong_value = [item[1:] for item in jinrong_list] #取各行数据列
    remove_mutilist_data_douao(jinrong_value)
    # 计算得到有息负债总额：
    sum_jinrong = [0] * (i_title_col-1)
    for row_data in jinrong_value:
        sum_jinrong = get_list_data_sum(sum_jinrong,row_data)

    # 计算好的总额，还原成千分位分隔，且保留两位小数位  
    formatted_jinrong=["{:,.2f}".format(num) for num in sum_jinrong]
    formatted_jinrong.insert(0,"∑金融资产总额")
    jinrong_list.append(formatted_jinrong)

    return jinrong_list

def get_lix_value(all_list):
    # 得到应收利息’+‘应收股利’之和，以便在‘其他应收款’里减掉
    row_guxis = [row for row in all_list if row[0] == '其中：应收利息']
    lixi_value = []
    if len(row_guxis)>0:
        row_guxi = row_guxis[0][1:]
        if any('' != item for item in row_guxi): #不是全空数值
            lixi_values = [repair_nulldata_2_zero(row_guxi)]
            remove_mutilist_data_douao(lixi_values)
            lixi_value = lixi_values[0]
            
    row_gulis = [row for row in all_list if row[0] == '应收股利']
    if len(row_gulis)>0:
        row_guli = row_gulis[0][1:]
        if any('' != item for item in row_guli): #不是全空数值
            lixi_values = [repair_nulldata_2_zero(row_guli)]
            remove_mutilist_data_douao(lixi_values)
            guli_value = lixi_values[0]
            if len(guli_value)>0:
                if len(lixi_value)>0:
                    lixi_value = get_list_data_sum(lixi_value,guli_value)
                else:
                    lixi_value = guli_value
            # else:
            #     lixi_value = lixi_values[0]
    return lixi_value

def get_repair_qtliudong(ld_row,jr_value,title):
    ld_data = ld_row[1:]
    ld_value = remove_list_data_douao(ld_data)
    substr_value = get_list_data_subtract(ld_value,jr_value)
    formatted_qtliudong=["{:,.2f}".format(num) for num in substr_value]
    formatted_qtliudong.insert(0,title)
    return formatted_qtliudong

# 获取周转性投入列表（周转资产-周转负债），带出周转投入总额数据以便后续计算
def get_zhouzhuan_data(old_list,sum_input,sum_zz_jtr,value_zongzichan):
    def get_repair_qtyingshou(ys_row,lx_value):
        ys_data = [ys_row[1:]]
        remove_mutilist_data_douao(ys_data)
        ys_value = ys_data[0]
        substr_value = get_list_data_subtract(ys_value,lx_value)
        formatted_qtyingshou=["{:,.2f}".format(num) for num in substr_value]
        formatted_qtyingshou.insert(0,'其他应收款')
        return formatted_qtyingshou
    

    def get_zz_asset(old_list,sum_yingshou):
        i_title_col = len(old_list[0])
        lx_value = get_lix_value(old_list) 
        #先得到利息，以便判断是否要在‘其他应收款’里减掉

        row_yingshou_titles = ['存货','应收账款','应收票据','银行承兑','其它承兑','应收款项融资','预付款项','应收保费','应收分保账款','应收分保合同准备金',
                           '其他应收款','长期应收款','合同资产','其他流动资产','一年内到期的非流动资产','递延所得税资产','发放贷款和垫款'] 
        yingshou_list = []
        # 像三七互娱这种，还有没有存货的情况
        cunhuo_row = [row for row in old_list if row[0] == '存货']
        if len(cunhuo_row)==0:
            old_list.insert(0, ['存货']+['0']*(i_title_col-1))
        for title in row_yingshou_titles:
            youxi_row = [row for row in old_list if row[0] == title]
            if len(youxi_row)>0:
                row_data = youxi_row[0]
                if any('' != item for item in row_data[1:]):
                    if row_data[0] == '其他流动资产':
                        if len(qtld_zz_jinrong) == i_title_col-1:
                            #其他流动资产部分为金融资产
                            copy_list = qtld_zz_jinrong[:]
                            qt_jr_value = remove_list_data_douao(copy_list)
                            repair_row = get_repair_qtliudong(repair_nulldata_2_zero(row_data),qt_jr_value,'其他流动资产')
                            yingshou_list.append(repair_row)
                        else:
                            #其他流动资产全部为经营资产
                            yingshou_list.append(repair_nulldata_2_zero(row_data)) 
                    elif row_data[0] == '一年内到期的非流动资产':
                        if len(ynndq_fld_zz_jinrong) == i_title_col-1:
                            #其他流动资产部分为金融资产
                            copy_list = ynndq_fld_zz_jinrong[:]
                            qt_jr_value = remove_list_data_douao(copy_list)
                            repair_row = get_repair_qtliudong(repair_nulldata_2_zero(row_data),qt_jr_value,'一年内到期的非流动资产')
                            yingshou_list.append(repair_row)
                        else:
                            #其他流动资产全部为经营资产
                            yingshou_list.append(repair_nulldata_2_zero(row_data))         
                    elif row_data[0] == '其他应收款':
                        if len(lx_value)>0:
                            # 得到应收款数值，然后减掉利息值，再格式化后回填
                            repair_row = get_repair_qtyingshou(repair_nulldata_2_zero(row_data),lx_value)
                            yingshou_list.append(repair_row)
                        else:
                            yingshou_list.append(repair_nulldata_2_zero(row_data))
                    elif row_data[0] == '应收票据':
                        yingshou_list.append(repair_nulldata_2_zero(row_data))
                        if len(data_bank_piaoju) == i_title_col-1:
                            yingshou_list.append(['* 其中银行承兑票据']+data_bank_piaoju)
                    else:
                        yingshou_list.append(repair_nulldata_2_zero(row_data))
                else:
                    print("cancel.全空数据:",row_data)
            else:
                print("not.find:",title)
        
        yingshou_value = [item[1:] for item in yingshou_list] #取各行数据列
        remove_mutilist_data_douao(yingshou_value)
        tmp_value = sum_yingshou
        for row_data in yingshou_value[1:]: # 计算得到（除存货之外的）应收资产总额：
            tmp_value = get_list_data_sum(tmp_value,row_data)
            
        if len(data_bank_piaoju) == i_title_col-1:
            #简单赋值是对象引用，remove_list_data_douao会改变tmp_data的值，也会影响data_bank_piaoju
            # 要改成副本赋值，才不会影响到data_bank_piaoju
            copy_list = data_bank_piaoju[:]
            value_bank = remove_list_data_douao(copy_list)
            tmp_value = get_list_data_subtract(tmp_value,value_bank)
            # tmp_value包含了‘银行承兑票据’的值，所以要减掉2次‘银行承兑票据’数值
            # value_substr = get_list_data_subtract(tmp_value,value_bank)
            # tmp_value = get_list_data_subtract(value_substr,value_bank)
        sum_yingshou[:] = tmp_value #切片将'应收总额'值带出，以便后面计算应收总额-应付总额来判断占用上下游资金情况
        
        formatted_zz_asset=["{:,.2f}".format(num) for num in tmp_value]
        formatted_zz_asset.insert(0,"∑周转性资产总额") #除存货之外的应收资产总额
        yingshou_list.append(formatted_zz_asset)
        # 周转资产总额/总资产
        value_zz_bili = calc_xsbl(tmp_value,value_zongzichan)
        yingshou_list.append(['周转资产/总资产']+value_zz_bili)
        fen_ge = ['-'] * i_title_col
        yingshou_list.append(fen_ge)
        
        data_cunhuo = yingshou_list[0]
        value_cunhuo = remove_list_data_douao(data_cunhuo[1:])
        yingshou_list.append(data_cunhuo) #存货放到后面
        # 存货/总资产
        value_cunhuo_bili = calc_xsbl(value_cunhuo,value_zongzichan)
        yingshou_list.append(['存货/总资产']+value_cunhuo_bili)
        yingshou_list.append(fen_ge)
        del yingshou_list[0]
        
        # 周转资产总额(应收总额+存货yingshou_value[0]) #错了要加存货增量，而不是+期末存货总量
        # sum_zz_asset[:] = tmp_value # sum_zz_asset[:] = get_list_data_sum(tmp_value,yingshou_value[0]) 
        #周转资产总额带出，后面计算周转资产总额-周转负债总额用
        # formatted_zz_asset=["{:,.2f}".format(num) for num in sum_zz_asset]
        # formatted_zz_asset.insert(0,"周转性资产总额(应收款+存货)")
        # yingshou_list.append(formatted_zz_asset)

        return yingshou_list

    # 周转性负债
    def get_zz_fuzai(old_list,sum_yingfu):
        row_yingfu_titles = ['应付账款','应付票据','预收款项','合同负债','卖出回购金融资产款','吸收存款及同业存放','代理买卖证券款','代理承销证券款', 
                         '应付职工薪酬','应交税费', '其他应付款','应付手续费及佣金','应付分保账款','持有待售负债','其他流动负债','其他非流动负债',
                         '长期应付款','长期应付职工薪酬','递延收益', '递延所得税负债',]
        # '预计负债',不属于应付项目，也不属于有息负债项目，而是或有负债
        yingfu_list = []
        for title in row_yingfu_titles:
            youxi_row = [row for row in old_list if row[0] == title]
            if len(youxi_row)>0:
                row_data = youxi_row[0]
                if any('' != item for item in row_data[1:]):
                    yingfu_list.append(repair_nulldata_2_zero(row_data))
                else:
                    print("cancel.全空数据:",row_data)
            else:
                print("not.find:",title)
                
        youxi_row = [row for row in old_list if '应付票据及应付账款' in row[0]]
        if len(youxi_row)>0:
            row_data = youxi_row[0]
            if any('' != item for item in row_data[1:]):
                newdata = ['应付账款']+row_data[1:]
                yingfu_list.append(repair_nulldata_2_zero(newdata))
            else:
                print("cancel.全空数据:",row_data)
        else:
            print("not.find:",title)
                
        
        yingfu_value = [item[1:] for item in yingfu_list] #取各行数据列
        remove_mutilist_data_douao(yingfu_value)
        # 计算得到应付资产总额：
        tmp_value = sum_yingfu
        for row_data in yingfu_value: 
            tmp_value = get_list_data_sum(tmp_value,row_data)  
        sum_yingfu[:] = tmp_value
        formatted_zz_fuzai=["{:,.2f}".format(num) for num in tmp_value]
        formatted_zz_fuzai.insert(0,"∑周转性负债总额")
        yingfu_list.append(formatted_zz_fuzai)
        value_zzfz_bli = calc_xsbl(tmp_value,value_zongzichan)
        yingfu_list.append(['周转负债/总资产']+value_zzfz_bli)
        fen_ge = ['-'] * i_title_col
        yingfu_list.append(fen_ge)
        
        # '预计负债',不属于应付项目，也不属于有息负债项目，而是或有负债
        # 信号意义：高预计负债可能暗示经营风险（如频繁诉讼）或社会责任（如环保投入），影响投资者判断。
        youxi_row = [row for row in old_list if row[0] == '预计负债']
        if len(youxi_row)>0:
            row_data = youxi_row[0]
            if any('' != item for item in row_data[1:]):
                yingfu_list.append(['！预计负债']+repair_nulldata_2_zero(row_data[1:]))
                fen_ge = ['-'] * i_title_col
                yingfu_list.append(fen_ge)
            else:
                print("cancel.全空数据:",row_data)
        

        return yingfu_list

    i_title_col = len(old_list[0])
    zz_input_list = [] #周转投入汇总表
    sum_yingshou = [0] * (i_title_col-1) #全部应收
    # sum_zz_asset = [0] * (i_title_col-1) #存货+全部应收
    zz_asset_list = get_zz_asset(old_list,sum_yingshou)
    zz_input_list += zz_asset_list #周转资产汇总表
    sum_yingfu = [0] * (i_title_col-1)
    zz_fuzai_list = get_zz_fuzai(old_list,sum_yingfu)
    zz_input_list += zz_fuzai_list #周转性负债汇总表
    # 应付大于预付：对上游有定价权
    # '应付账款'+'应付票据'> '预付款项'
    data_yingf_kuan = get_single_data(old_list,'应付账款')
    value_yingf_kuan = remove_list_data_douao(data_yingf_kuan[1:])
    data_yingf_piaoju= get_single_data(old_list,'应付票据')
    value_yingf_piaoju = remove_list_data_douao(data_yingf_piaoju[1:])
    value_yingfu_he = get_list_data_sum(value_yingf_kuan,value_yingf_piaoju)
    formatted_input=["{:,.2f}".format(num) for num in value_yingfu_he]
    formatted_input.insert(0,"销售应付款")
    zz_input_list.append(formatted_input)
    
    data_yuf_kuan = get_single_data(old_list,'预付款项')
    value_yuf_kuan = remove_list_data_douao(data_yuf_kuan[1:])
    data_yuf_kuan[0]="销售预付款"
    zz_input_list.append(data_yuf_kuan)
    
    value_shangyou = get_list_data_subtract(value_yingfu_he,value_yuf_kuan)
    formatted_input=["{:,.2f}".format(num) for num in value_shangyou]
    formatted_input.insert(0,"•占用上游资金(销售应付款-销售预付款)")
    zz_input_list.append(formatted_input)
    
    # 应收小于预收：对下游戏有定价权
    # '应收账款','应收票据' < '预收款项'+'合同负债'
    data_yingshou_kuan = get_single_data(old_list,'应收账款')
    value_yingshou_kuan = remove_list_data_douao(data_yingshou_kuan[1:])
    data_yingshou_piaoju= get_single_data(old_list,'应收票据')
    value_yingshou_piaoju = remove_list_data_douao(data_yingshou_piaoju[1:])
    value_yingshou_he = get_list_data_sum(value_yingshou_kuan,value_yingshou_piaoju)
    data_yingshou_rz = get_single_data(old_list,'应收款项融资')
    value_yingshou_rz = remove_list_data_douao(data_yingshou_rz[1:])
    value_yingshou_he = get_list_data_sum(value_yingshou_he,value_yingshou_rz)
    # if len(data_bank_piaoju) == i_title_col-1:
    #     #简单赋值是对象引用，remove_list_data_douao会改变tmp_data的值，也会影响data_bank_piaoju
    #     # 要改成副本赋值，才不会影响到data_bank_piaoju
    #     copy_list = data_bank_piaoju[:]
    #     value_bank = remove_list_data_douao(copy_list)
    #     # tmp_value包含了‘银行承兑票据’的值，所以要减掉2次‘银行承兑票据’数值
    #     value_yingshou_he = get_list_data_subtract(value_yingshou_he,value_bank)
    formatted_yingshou=["{:,.2f}".format(num) for num in value_yingshou_he]
    formatted_yingshou.insert(0,"销售应收款")
    
    data_yushou_kuan = get_single_data(old_list,'预收款项')
    value_yushou_kuan = remove_list_data_douao(data_yushou_kuan[1:])
    data_yushou_hetong = get_single_data(old_list,'合同负债')
    value_yushou_hetong = remove_list_data_douao(data_yushou_hetong[1:])
    value_yushou_he = get_list_data_sum(value_yushou_kuan,value_yushou_hetong)
    formatted_yushou=["{:,.2f}".format(num) for num in value_yushou_he]
    formatted_yushou.insert(0,"销售预收款")
    zz_input_list.append(formatted_yushou) 
    zz_input_list.append(formatted_yingshou) 
    
    value_xiayou = get_list_data_subtract(value_yushou_he,value_yingshou_he)
    formatted_input=["{:,.2f}".format(num) for num in value_xiayou]
    formatted_input.insert(0,"•占用下游资金(销售预收款-销售应收款)")
    zz_input_list.append(formatted_input)
    
    # sum_yingshou - sum_yingfu = 无息占用资金(应收-应付)
    sum_zy = get_list_data_subtract(sum_yingfu,sum_yingshou)
    formatted_zy=["{:,.2f}".format(num) for num in sum_zy]
    formatted_zy.insert(0,"•无息占用周转资金(周转负债-周转资产)")
    zz_input_list.append(formatted_zy)

    # sum_zz_asset - sum_yingfu = 周转性投入总额(周转性资产-周转性负债)
    data_cunhuo = get_single_data(old_list,'存货')
    value_cunhuo = remove_list_data_douao(data_cunhuo[1:]) 
    value_cunhuo_add = calc_growing_value(value_cunhuo) #存货增量
    formatted_cunhuo_add=["{:,.2f}".format(num) for num in value_cunhuo_add]
    zz_input_list.append(["存货增加额"]+formatted_cunhuo_add)
    
    sum_zz_cunhuo = get_list_data_sum(sum_yingshou,value_cunhuo_add) 
    sum_zz_jtr[:] = get_list_data_subtract(sum_zz_cunhuo,sum_yingfu)
    formatted_input=["{:,.2f}".format(num) for num in sum_zz_jtr]
    formatted_input.insert(0,"•周转净投入(周转资产-周转负债+存货增量)")
    zz_input_list.append(formatted_input)
    value_ys_b_zzc = calc_xsbl(value_yingshou_he,value_zongzichan) 
    zz_input_list.append(['销售应收款/总资产']+value_ys_b_zzc)  #应收/总资产
    # 应收+存货-应付=周转净投入
    sum_zz_asset = get_list_data_sum(sum_yingshou,value_cunhuo) 
    sum_input[:] = get_list_data_subtract(sum_zz_asset,sum_yingfu) #切片将值带出，以便后面计算总经营资产
    
   

    return zz_input_list

# 获取长期经营资产列表及总额
def get_longzz_data(old_list,sum_long_asset):
    row_long_operate_titles = ['投资性房地产','固定资产','在建工程','生产性生物资产','油气资产','使用权资产','无形资产','开发支出','商誉','长期待摊费用','其他非流动资产']
    longzz_list = []
    for title in row_long_operate_titles:
        youxi_row = [row for row in old_list if row[0] == title]
        if len(youxi_row)>0:
            row_data = youxi_row[0]
            if any('' != item for item in row_data[1:]):
                if row_data[0] == '其他非流动资产':
                    if len(qtfld_zz_jinrong) == 6:
                        #其他流动资产部分为金融资产
                        copy_list = qtfld_zz_jinrong[:]
                        qt_jr_value = remove_list_data_douao(copy_list)
                        repair_row = get_repair_qtliudong(repair_nulldata_2_zero(row_data),qt_jr_value,'其他非流动资产')
                        longzz_list.append(repair_row)
                    else:
                        #其他流动资产全部为经营资产
                        longzz_list.append(repair_nulldata_2_zero(row_data)) 
                else:
                    longzz_list.append(repair_nulldata_2_zero(row_data))
            else:
                print("cancel.全空数据:",row_data)
        else:
            print("not.find:",title)
    
    long_value = [item[1:] for item in longzz_list] #取各行数据列
    remove_mutilist_data_douao(long_value)
    # 计算得到有息负债总额：
    tmp_value = sum_long_asset
    for row_data in long_value:
        tmp_value = get_list_data_sum(tmp_value,row_data)
    sum_long_asset[:] = tmp_value
    # 计算好的总额，还原成千分位分隔，且保留两位小数位  
    formatted_jinrong=["{:,.2f}".format(num) for num in tmp_value]
    formatted_jinrong.insert(0,"∑长期经营资产总额")
    longzz_list.append(formatted_jinrong)

    return longzz_list

# 获取单行表格数据(如股东权益、长期股权投资等)
def get_single_data(old_list,target_title):
    result = [target_title,'0','0','0','0','0','0']
    target_rows = [row for row in old_list if row[0] == target_title] #row[0]还有可能为：所有者权益（或股东权\n益）合计
    if len(target_rows)>0:
        result = repair_nulldata_2_zero(target_rows[0])
    return result
def get_mohu_single_data(old_list,target_title,title_start,title_end):
    result = [target_title,'0','0','0','0','0','0']
    target_rows = [row for row in old_list if row[0].startswith(title_start) and row[0].endswith(title_end)] 
    #row[0]还有可能为：所有者权益（或股东权\n益）合计
    if len(target_rows)>0:
        result = repair_nulldata_2_zero(target_rows[0])
    return result
def get_contain_single_data(old_list,target_title,subtitle):
    result = [target_title,'0','0','0','0','0','0']
    target_rows = [row for row in old_list if subtitle in row[0]] 
    #row[0]还有可能为：所有者权益（或股东权\n益）合计
    if len(target_rows)>0:
        result = repair_nulldata_2_zero(target_rows[0])
    return result
# 根据营收列表和成本列表，计算得到毛利(类型),并格式化百分比字符串列表
def calc_maoli(value_yysr,value_yycb):
    value_maoli = [(float(revenue) - float(cost))/float(revenue) for revenue, cost in zip(value_yysr, value_yycb)]
    formatted_maoli=[f"{gpr*100:.2f}%" for gpr in value_maoli]
    return formatted_maoli
# 根据销售费用和营收列表，计算得到销售费率(类型),并格式化百分比字符串列表
def calc_xsbl(value_xsfy,value_yysr):
    value_bl = [0 if not float(revenue) else float(cost)/float(revenue) for cost,revenue in zip(value_xsfy, value_yysr)]
    formatted_bili=[f"{gpr*100:.2f}%" for gpr in value_bl]
    return formatted_bili
# 计算贡献率(占比*收益率，两个百分比相乘)
def calc_gxlv(data_bl,data_sy):
    # 原始列表（百分比字符串)>转换为浮点数列表
    list1_floats = [float(s.strip('%')) / 100 for s in data_bl]  
    list2_floats = [float(s.strip('%')) / 100 for s in data_sy]  
    # 一一相乘并转换回百分比字符串  
    result_list = [f'{int(x * y * 10000) / 100:.2f}%' for x, y in zip(list1_floats, list2_floats)]
    return result_list
# 计算类似：去税息利润=息税前利润*(1-税率)
def calc_qslr(data_xqlr,data_slv):
    # data_xqlr、data_slv及皆为浮点字符串列表，先转成浮点数，然后相乘，得到乘积，并保留2位小数
    list1_floats = [float(s) for s in data_xqlr]  
    list2_floats = [float(s) for s in data_slv]  
    # 一一相乘并转换为浮点字符串  
    result_list = [f'{float(x * y):.2f}' for x, y in zip(list1_floats, list2_floats)]
    return result_list

# 计算贡献率之和，两个百分比相加
def calc_gxlv_sum(data_bl,data_sy):
    # 原始列表（百分比字符串)>转换为浮点数列表
    list1_floats = [float(s.strip('%')) / 100 for s in data_bl]  
    list2_floats = [float(s.strip('%')) / 100 for s in data_sy]  
    # 一一相加并转换回百分比字符串  
    result_list = [f'{int((x + y) * 10000) / 100:.2f}%' for x, y in zip(list1_floats, list2_floats)]
    return result_list
# 计算净现比，两个数据相除，保留2位小数 
# 根据净利润列表和现金流列表，得到净现比(现金/净利润，长期大于1为好)，并格式化为小数
def calc_jxb(value_xjl,value_jlr):
    value_bl = [0 if float(revenue)==0  else float(cost)/float(revenue)  for cost,revenue in zip(value_xjl,value_jlr)]
    formatted_bili=["{:,.2f}".format(num) for num in value_bl]
    return formatted_bili
# 加税营业收
def calc_jsys(value_yysr):
    # 营业收入×117%≈销售 商品、提供劳务收到的现金+应收账款、应收票据增加额
    value_jsys = [0 if float(revenue)==0  else float(revenue)*1.17  for revenue in value_yysr]
    formatted_jsys=["{:,.2f}".format(num) for num in value_jsys]
    return formatted_jsys
# 计算增长率类型，(value_list[0]-value_list[1])/value_list[1],最后一项补0,并且返回百分比
def calc_grow_lv(value_list):
    value_bl = [0 if not float(value_list[i+1]) else (float(value_list[i]) - float(value_list[i+1])) / float(value_list[i+1]) for i in range(0, len(value_list)-1)]
    value_bl.append(0)
    formatted_bili=[f"{gpr*100:.2f}%" for gpr in value_bl]
    return formatted_bili
# 得到前后两个值的平均值，组成一个新的列表，最后一个值的平均值为本身
def calc_average_value(value_list):
    value_average = [(float(value_list[i]) + float(value_list[i+1])) / 2 for i in range(0, len(value_list)-1)]
    value_average.append(float(value_list[-1])) #最后一个值的平均值为本身
    return value_average
# 获取存货增量，期末-期初
def calc_growing_value(value_list):
    value_growing = [(float(value_list[i]) - float(value_list[i+1])) for i in range(0, len(value_list)-1)]
    value_growing.append(float(value_list[-1])) #最后一个值的增量值为本身
    return value_growing
    
# 从利润表中查找指定标题项，并且查到后在利润表中将此行删除
def get_lirun_report_rowdata(title,list_lirun):
    if len(list_lirun)==0:
        print("---list_lirun is null：",title)
        return [title]+['0.0']*6 #全部取完了，则说明是表中没有项目，直接返回0即可
    row_target = [(index,row) for index,row in enumerate(list_lirun) if row[0] == title]
    if len(row_target)>0:
        # print("---find.in.list_lirun:",title)
        index = row_target[0][0]
        del list_lirun[index]
        return row_target[0][1]
    else:
        # print("---notfind.in.list_lirun:",title)
        return [title]+['0.0']*(len(list_lirun[0])-1) #利润表数据要参与计算，所以如果没找到此项，则默认0代替，以保证肯定有正确返回

def pro_my_fuzai_report_tofile(report_fuzai,report_lirun,report_xianjin,report_xianjin_buchong,
                               bank_piaoju,qtld_jinrong,value_ynndq_fld_jinrong,value_qtfld_jinrong,filepath,zong_guben):
    # 按要求生成指定格式的负债表数据
    data_bank_piaoju[:] = bank_piaoju
    qtld_zz_jinrong[:] = qtld_jinrong
    ynndq_fld_zz_jinrong[:] = value_ynndq_fld_jinrong
    qtfld_zz_jinrong[:] = value_qtfld_jinrong
    list_title = report_fuzai[0]
    i_title_col = len(list_title)
    del report_fuzai[0]
    del report_lirun[0]
    
    print('\n')
    
    all_list = []
    all_list.append(list_title)
    # 先看整体，总资产是否有增长，是借钱带来的增长，还是利润带来的增长
    # 资产总计
    data_zongzichan = get_single_data(report_fuzai,'资产总计')
    value_zongzichan = remove_list_data_douao(data_zongzichan[1:])
    all_list.append(data_zongzichan)
    # 所有者权益（或股东权益）合计
    quanyi_row = get_single_data(report_fuzai,'所有者权益合计')
    quanyi_value = remove_list_data_douao(quanyi_row[1:])
    all_list.append(quanyi_row)
    
    value_zz_je = calc_growing_value(value_zongzichan) #期末-期初
    formatted_zz_je=["{:,.2f}".format(num) for num in value_zz_je]
    all_list.append(['资产增长净额']+formatted_zz_je)
    
    value_tmp_fz = get_list_data_subtract(value_zongzichan,quanyi_value) #每期负债 = 负债合计
    formatted_fzai=["{:,.2f}".format(num) for num in value_tmp_fz]
    all_list.append(['负债总额']+formatted_fzai)
    
    value_xzfz_je = calc_growing_value(value_tmp_fz) #期末增长的负债，
    formatted_xzfz_je=["{:,.2f}".format(num) for num in value_xzfz_je]
    all_list.append(['新增借款']+formatted_xzfz_je)
    
    # 除新增负债后的增长净额
    value_zz_je = get_list_data_subtract(value_zz_je,value_xzfz_je) #新增的资产-新增的负债 = 纯赚到的钱，
    formatted_zz_je=["{:,.2f}".format(num) for num in value_zz_je]
    all_list.append(['纯挣净额(新增资产-新增借款)']+formatted_zz_je)
    
    data_hebing_jlr = get_lirun_report_rowdata('净利润',report_lirun)
    value_hebing_jlr = remove_list_data_douao(repair_nulldata_2_zero(data_hebing_jlr[1:]))
    data_gm_jlr = get_lirun_report_rowdata('归母净利润',report_lirun)
    all_list.append(data_gm_jlr)
    value_gm_jlr = remove_list_data_douao(repair_nulldata_2_zero(data_gm_jlr[1:]))
    # 京沪高铁比较奇葩，2019年年报里没有合并报表一说，利润表里也没有归母净利润一说
    for i in range(len(value_gm_jlr)):
        if value_gm_jlr[i] == '0' or value_gm_jlr[i] == '0.0':
            # 若当前项为 '0.0'，则用 value_jlr 对应位置的值替换
            value_gm_jlr[i] = value_hebing_jlr[i]
            data_gm_jlr[i+1] = data_hebing_jlr[i+1]
        
    value_fh_chae = get_list_data_subtract(value_gm_jlr,value_zz_je) #净利润-纯赚到的钱，差额部分基本上就是分红分掉的钱了
    formatted_fh_chae=["{:,.2f}".format(num) for num in value_fh_chae]
    all_list.append(['差额(归母净利润-纯挣净额)']+formatted_fh_chae)
    fen_ge = ['-'] * i_title_col
    # ----------------------
    all_list.append(fen_ge)
    
    # 再看有息负债，占比总资产，是否
     #有息负债总表，及有息总额数据
    sum_youxi = [0] * (i_title_col-1)
    youxi_list = get_youxifuzai_data(report_fuzai,sum_youxi)
    all_list += youxi_list 
    # 有息负债/总资产
    data_youxi_lv = calc_xsbl(sum_youxi,value_zongzichan)
    all_list.append(['有息负债率(有息负债/总资产<30%)']+data_youxi_lv)
    
    data_lxfy = get_lirun_report_rowdata('利息费用',report_lirun)
    value_lxfy = remove_list_data_douao(repair_nulldata_2_zero(data_lxfy[1:])) 
    tmp_bilv = calc_xsbl(value_lxfy,sum_youxi)
    all_list.append(['负债利率(利息费用/有息债)']+tmp_bilv)
    # ----------------------
    all_list.append(fen_ge)
    
     # 总有息负债+股东权益=总本金
    sum_all_xianjin = get_list_data_sum(sum_youxi,quanyi_value) 
    formatted_all_xianjin=["{:,.2f}".format(num) for num in sum_all_xianjin]
    formatted_all_xianjin.insert(0,"∑股东筹资总本金(股东权益+有息借款)")
    all_list.append(formatted_all_xianjin)
     # ----------------------
    all_list.append(fen_ge)
    
    # 金融资产总表
    jinrong_list = get_jinrong_data(report_fuzai)
    all_list += jinrong_list
    
    tmp_jrzc = jinrong_list[-1]
    value_jrzc = remove_list_data_douao(repair_nulldata_2_zero(tmp_jrzc[1:]))
    tmp_bilv = calc_jxb(value_jrzc,sum_youxi) #金融资产能覆盖有息负债
    all_list.append(['金融资产/有息负债']+tmp_bilv)
    data_huobi =jinrong_list[0] # =get_single_data(report_fuzai,'货币资金')
    value_huobi = remove_list_data_douao(data_huobi[1:])
    tmp_bilv = calc_jxb(value_huobi,sum_youxi) #如果贷币资金能覆盖有息负债就更好了
    all_list.append(['货币资金/有息负债']+tmp_bilv)
    # --------------
    all_list.append(fen_ge)
    # 生产资产(长期经营资产)
    # 周转资产
    # 其他资产
    # 周转负债
    # 其他负债
    
    # 现金及现金等价物÷有息负债≥1
    
    # 生产资产÷总资产；应收÷总资产；非主业资产÷总资产
    
    # 周转性投入
    sum_input = [0] * (i_title_col-1) #周转性投入总额
    sum_zz_jtr = [0] * (i_title_col-1) #周转性净投入
    sum_zz_list = get_zhouzhuan_data(report_fuzai,sum_input,sum_zz_jtr,value_zongzichan)
    all_list += sum_zz_list
    # ---------------
    all_list.append(fen_ge)


    gm_quanyi_row = get_single_data(report_fuzai,'归母权益合计')
    gm_quanyi_value = remove_list_data_douao(gm_quanyi_row[1:])
    # 长期经营资产
    sum_long_asset = [0] * (i_title_col-1) #长期经营资产总额
    long_zz_list = get_longzz_data(report_fuzai,sum_long_asset)
    all_list += long_zz_list
    data_zc_bz = calc_xsbl(sum_long_asset,value_zongzichan)
    all_list.append(["资本比重(长期经营资产总额/总资产)"]+data_zc_bz)
    data_shangyu = get_single_data(report_fuzai,'商誉')
    value_shangyu = remove_list_data_douao(data_shangyu[1:])
    tmp_shangyu_quanyi = calc_xsbl(value_shangyu,gm_quanyi_value)
    all_list.append(["商誉占比(商誉/归母股东权益<30%)"]+tmp_shangyu_quanyi)
    # 商誉/净资产<30%
    # ---------------
    all_list.append(fen_ge)
    
    #------利润表的解析填充
    # ----------------
    # 只填充数据，计算位置预留着即可，由numbers手动拉取?
    # 营业收入
    # 营业成本
    # 销售费用
    # 研发费用
    data_yysr = get_lirun_report_rowdata('营业收入',report_lirun)
    value_yysr = remove_list_data_douao(repair_nulldata_2_zero(data_yysr[1:]))
    
    # 长期经营资产总额/总本金
    # 长期经营资产总额/营收
    
    data_zc_mjd = calc_xsbl(sum_long_asset,value_yysr)
    all_list.append(["资本密集度(长期经营资产总额/营业收入)"]+data_zc_mjd)
     # ---------------
    all_list.append(fen_ge)
    
    all_list.append(data_yysr)
    
    data_yscb = get_lirun_report_rowdata('营业成本',report_lirun)
    all_list.append(data_yscb)
    value_yycb = remove_list_data_douao(repair_nulldata_2_zero(data_yscb[1:]))
    
    data_sjjfj = get_lirun_report_rowdata('税金及附加',report_lirun)
    all_list.append(data_sjjfj)
    value_sjjfj = remove_list_data_douao(repair_nulldata_2_zero(data_sjjfj[1:]))
    
    data_xscb = get_lirun_report_rowdata('销售费用',report_lirun)
    all_list.append(data_xscb)
    value_xscb = remove_list_data_douao(repair_nulldata_2_zero(data_xscb[1:]))
    
    data_glcb = get_lirun_report_rowdata('管理费用',report_lirun)
    all_list.append(data_glcb)
    value_glcb = remove_list_data_douao(repair_nulldata_2_zero(data_glcb[1:]))
    
    data_yfcb = get_lirun_report_rowdata('研发费用',report_lirun)
    all_list.append(data_yfcb)
    value_yfcb = remove_list_data_douao(repair_nulldata_2_zero(data_yfcb[1:]))
    
    tmp_data = get_lirun_report_rowdata('财务费用',report_lirun)
    all_list.append(tmp_data)
    value_cwfy = remove_list_data_douao(repair_nulldata_2_zero(tmp_data[1:]))  
    # 利息费用
    all_list.append(['其中：利息费用']+data_lxfy[1:])
    # 4费
    value_tmp = get_list_data_sum(value_xscb,value_glcb)
    value_sfcb = get_list_data_sum(value_tmp,value_yfcb)
    value_sfall = get_list_data_sum(value_sfcb,value_lxfy)
    formatted_sfcb=["{:,.2f}".format(num) for num in value_sfall]
    formatted_sfcb.insert(0,"∑四费总成本(销+管+研+利息)")
    all_list.append(formatted_sfcb)
    
    # 毛利
    formatted_maoli = calc_maoli(value_yysr,value_yycb)
    formatted_maoli.insert(0,'毛利')
    all_list.append(formatted_maoli)
    # 销售费率
    formatted_xsfl = calc_xsbl(value_xscb,value_yysr)
    formatted_xsfl.insert(0,'•销售费率(销售费用/营业收入)')
    all_list.append(formatted_xsfl)
    # 管理费率
    formatted_glfl = calc_xsbl(value_glcb,value_yysr)
    formatted_glfl.insert(0,'管理费率(管理费用/营业收入)')
    all_list.append(formatted_glfl)
    # 研发费率
    formatted_yffl = calc_xsbl(value_yfcb,value_yysr)
    formatted_yffl.insert(0,'•研发费率(研发费用/营业收入)')
    all_list.append(formatted_yffl)
      
    # 财务费率
    formatted_cwfl = calc_xsbl(value_lxfy,value_yysr)
    formatted_cwfl.insert(0,'财务费率(利息费用/营业收入)')
    all_list.append(formatted_cwfl)
    # 4费占比
    formatted_sffl = calc_xsbl(value_sfall,value_yysr)
    formatted_sffl.insert(0,'四费占比(销+管+研+利息/营业收入)')
    all_list.append(formatted_sffl)
    
    # 销售商品、提供劳务收到的现金≥营业收入；
    # 营业收入×117%≈销售 商品、提供劳务收到的现金+应收账款、应收票据增加额。这个差别在 10%上下波动，基本属于大体正常
    data_jsys = calc_jsys(value_yysr)
    all_list.append(['加税营收(营业收入×117%)≈收现']+data_jsys)
    data_xs_xj = get_single_data(report_xianjin,'销售商品收到的现金')
    value_xs_xj = remove_list_data_douao(data_xs_xj[1:])
    all_list.append(data_xs_xj)
    # 销售商品、提供劳务收到的现金/营业收入
    data_sxbli = calc_jxb(value_xs_xj,value_yysr)
    all_list.append(['收现比(销售现金/营收)']+data_sxbli)
    
    #-----------
    all_list.append(fen_ge)
    
    # all_list.append(data_jlr)
    all_list.append(data_gm_jlr)
    # 净利率=归母净利润÷营业收入
    data_jinglilv = calc_xsbl(value_gm_jlr,value_yysr)
    all_list.append(['净利率(归母净利润÷营业收入)']+data_jinglilv)
    
    row_xjll_je = get_single_data(report_xianjin,'经营活动产生的现金流量净额')
    all_list.append(row_xjll_je) #现金流
    value_xjl = remove_list_data_douao(repair_nulldata_2_zero(row_xjll_je[1:]))
    formatted_jxb = calc_jxb(value_xjl,value_gm_jlr)
    formatted_jxb.insert(0,'•净现比(现金流净额/归母净利润)')
    all_list.append(formatted_jxb)
    # 净资产收益率ROE(净利润/股东权益)
    all_list.append(gm_quanyi_row)
    average_qy = calc_average_value(gm_quanyi_value)
    data_roe = calc_xsbl(value_gm_jlr,average_qy)
    all_list.append(['•ROE(归母净利润/平均归母权益)']+data_roe)
    # 营业利润率=（营业收入-营业成本-四费）÷营业收入
    value_yylr_fy = get_list_data_subtract(value_yysr,value_yycb)
    value_yylr_fy = get_list_data_subtract(value_yylr_fy,value_sfall)
    data_yylr_bl = calc_xsbl(value_yylr_fy,value_yysr)
    all_list.append(['营业利润率((营业收入-营业成本-四费)/营业收入)']+data_yylr_bl)
    #少数股东损益/少数股东权益(如果少数股东roe>归母roe，说明有可能少数股东掌握了资源，或者侵占了公司收益)
    data_ssgd_sy = get_lirun_report_rowdata('少数股东损益',report_lirun)
    all_list.append(data_ssgd_sy)
    data_ssdg_qy = get_single_data(report_fuzai,'少数股东权益')
    all_list.append(data_ssdg_qy)
    value_ssgd_sy = remove_list_data_douao(data_ssgd_sy[1:])
    value_ssgd_qy = remove_list_data_douao(data_ssdg_qy[1:])
    data_ss_roe = calc_xsbl(value_ssgd_sy,value_ssgd_qy)
    all_list.append(['少数股东ROE(少数股东损益/少数股东权益)']+data_ss_roe)
    # ---------
    all_list.append(fen_ge)
    
    #'营业利润'
    tmp_data = get_lirun_report_rowdata('营业利润',report_lirun)
    all_list.append(tmp_data)
    value_yylr = remove_list_data_douao(repair_nulldata_2_zero(tmp_data[1:]))
    # 核心营业利润=营业收入-营业成本-税金及附加-销售费用-管理费用-研发费用-财务费用(用利息费用代替,利息收不做为核心生产利润)
    value_hxlr = get_list_data_subtract(value_yysr,value_yycb)
    value_hxlr = get_list_data_subtract(value_hxlr,value_sjjfj)
    value_hxlr = get_list_data_subtract(value_hxlr,value_sfall)
    formatted_hexinlirun=["{:,.2f}".format(num) for num in value_hxlr]
    formatted_hexinlirun.insert(0,"核心利润")
    all_list.append(formatted_hexinlirun)
    
    # 息税前利润=营业收入-营业成本-税金及附加-销售费用-管理费用-研发费用-其他收益-投资收益-公允价值变动收益-资产处置收益
    # 可以近似得出：息税前利润 = 财务费用(利息费用-利息收入) + 营业利润 
    value_xqlr = get_list_data_sum(value_yylr,value_cwfy)
    formatted_xqlirun=["{:,.2f}".format(num) for num in value_xqlr]
    formatted_xqlirun.insert(0,"息税前利润")
    all_list.append(formatted_xqlirun)
    
    # 其他收益
    tmp_data = get_lirun_report_rowdata('其他收益',report_lirun)
    all_list.append(tmp_data)
    value_qtly = remove_list_data_douao(repair_nulldata_2_zero(tmp_data[1:]))
    
    # 资产处置收益
    tmp_data = get_lirun_report_rowdata('资产处置收益',report_lirun)
    all_list.append(tmp_data)
    value_zcczsy = remove_list_data_douao(repair_nulldata_2_zero(tmp_data[1:]))
    
    # 息税前利润 - 其他收益 - 资产处置收益 = 扣非息前利润
    value_kfxqlr = get_list_data_subtract(value_xqlr,value_qtly)
    value_kfxqlr = get_list_data_subtract(value_kfxqlr,value_zcczsy)
    formatted_rowdata=["{:,.2f}".format(num) for num in value_kfxqlr]
    formatted_rowdata.insert(0,"扣非息税前利润")
    all_list.append(formatted_rowdata)    
    
    tmp_lrze = get_lirun_report_rowdata('利润总额',report_lirun)
    all_list.append(tmp_lrze)
    value_lrze = remove_list_data_douao(repair_nulldata_2_zero(tmp_lrze[1:]))
    tmp_sdsfy = get_lirun_report_rowdata('所得税费用',report_lirun)
    all_list.append(tmp_sdsfy)
    value_sdsfy = remove_list_data_douao(repair_nulldata_2_zero(tmp_sdsfy[1:]))
    
    # -------------------------------
    all_list.append(fen_ge)
    # 总本金
    # all_list.append(formatted_all_xianjin)
    # 息前回报率（息前利润/总本金)
    data_xqhblv = calc_xsbl(value_xqlr,sum_all_xianjin)
    all_list.append(['•息前回报率(息税前利润/总本金)']+data_xqhblv)
    # 扣非息前回报率（扣非息前利润/总本金)
    tmp_bilv = calc_xsbl(value_kfxqlr,sum_all_xianjin)
    all_list.append(['扣非息前回报率（扣非息税前利润/总本金)']+tmp_bilv)
    
    tmp_bilv = calc_xsbl(value_xqlr,sum_long_asset)
    all_list.append(['生产利润率(息税前利润/长期经营资产)(显著高于12%为轻资产)']+tmp_bilv)
    
    # 投入资本回报率（ROIC）= 息税前利润*(1-税率)/ 总本金(即股东权益+有息负债)
    # 税率 = 所得税费用/利润总额
    value_shuilv=calc_jxb(value_sdsfy,value_lrze)
    data_suilv = [f"{float(num) * 100:.0f}%" for num in value_shuilv]
    all_list.append(["所得税税率(所得税费用/利润总额)"]+data_suilv)  
    tmp_slv_sub = get_list_data_subtract(['1','1','1','1','1','1'],value_shuilv) #可以简写为：['1']*6
    value_qslr = calc_qslr(value_xqlr,tmp_slv_sub)#去税利润
    tmp_tzhblv = calc_xsbl(value_qslr,sum_all_xianjin) #去税利润/总本金 = 投入资本回报率
    all_list.append(['•资本回报率[ROIC=息税前利润*(1-税率)/总本金]']+tmp_tzhblv)
    
    # # 有息负债率
    # tmp_bilv = calc_xsbl(sum_youxi,sum_all_xianjin)
    # all_list.append(['有息负债率(有息债/总本金)']+tmp_bilv)
    # 负债利率(利息费用/有息债)
    # ----------------------
    all_list.append(fen_ge)    
    # 投向>长期股权投资
    guquan_row = get_single_data(report_fuzai,'长期股权投资')
    all_list.append(guquan_row)
    # 长期股权资产占比(长期股权投资/总本金)
    value_guquan = remove_list_data_douao(repair_nulldata_2_zero(guquan_row[1:]))
    tmp_bilv = calc_xsbl(value_guquan,sum_all_xianjin)
    zbj_sylv = tmp_bilv #总本金使用率
    all_list.append(['长期股权资产占比(长期股权投资/股东筹资总本金)']+tmp_bilv)
    # 长期股权收益
    tmp_data = get_lirun_report_rowdata('长期股权投资收益',report_lirun)
    all_list.append(tmp_data)
    # 长期股权收益率(股权投资收益/长期股权投资)
    value_guquan_sy = remove_list_data_douao(repair_nulldata_2_zero(tmp_data[1:]))
    tmp_sy = calc_xsbl(value_guquan_sy,value_guquan)
    all_list.append(['长期股权收益率(股权投资收益/长期股权投资)']+tmp_sy)
    # 长期股权收益贡献率(资金占比*收益率)
    tmp_gx_lv_gq = calc_gxlv(tmp_bilv,tmp_sy)
    all_list.append(['长期股权收益贡献率']+tmp_gx_lv_gq)
    # -----------
    all_list.append(fen_ge)
    
    # 投向>金融资产
    tmp_jrzc = jinrong_list[-1]
    all_list.append(tmp_jrzc)
    # 金融资产占比(金融资产/总本金)
    value_jrzc = remove_list_data_douao(repair_nulldata_2_zero(tmp_jrzc[1:]))
    tmp_bilv = calc_xsbl(value_jrzc,sum_all_xianjin)
    all_list.append(['金融资产占比(金融资产/股东筹资总本金)']+tmp_bilv)
    zbj_sylv = calc_gxlv_sum(zbj_sylv,tmp_bilv)
    # 金融资产收益(利息收入+投资收益-股权投资收益)
    data_lxsr = get_lirun_report_rowdata('利息收入',report_lirun,)
    value_lxsr = remove_list_data_douao(repair_nulldata_2_zero(data_lxsr[1:]))
    data_tzsy = repair_nulldata_2_zero(get_lirun_report_rowdata('投资收益',report_lirun))
    value_tzsy = remove_list_data_douao(repair_nulldata_2_zero(data_tzsy[1:]))
    value_jrzc_sy = get_list_data_sum(value_lxsr,value_tzsy)
    value_jrzc_sy = get_list_data_subtract(value_jrzc_sy,value_guquan_sy)
    formatted_row=["{:,.2f}".format(num) for num in value_jrzc_sy]
    all_list.append(['金融资产收益(利息收入+投资收益-股权投资收益)']+formatted_row)
    # 金融资产收益率(金融资产收益/金融资产)
    tmp_sy = calc_xsbl(value_jrzc_sy,value_jrzc)
    all_list.append(['金融资产收益率(金融资产收益/金融资产)']+tmp_sy)
    # 金融资产收益贡献率
    tmp_gx_lv_jl = calc_gxlv(tmp_bilv,tmp_sy)
    all_list.append(['金融资产收益贡献率']+tmp_gx_lv_jl)
    # -----------
    all_list.append(fen_ge)
    
    # 长期经营资产总额+周转性投入总额 = 经营资产投入总额
    manager_asset = get_list_data_sum(sum_long_asset,sum_input)
    formatted_manager=["{:,.2f}".format(num) for num in manager_asset]
    all_list.append(['∑经营资产总额(长期资产+应收-应付+存货)']+formatted_manager)
    # 经营资产占比(经营资产总额/总本金)
    tmp_bilv = calc_xsbl(manager_asset,sum_all_xianjin)
    all_list.append(['经营资产占比(经营资产总额/股东筹资总本金)']+tmp_bilv)
    zbj_sylv = calc_gxlv_sum(zbj_sylv,tmp_bilv)
    # 经营资产收益(息前利润-金融收益-股权收益)
    tmp_value = get_list_data_sum(value_jrzc_sy,value_guquan_sy)
    value_manager_sy = get_list_data_subtract(value_xqlr,tmp_value)
    formatted_row=["{:,.2f}".format(num) for num in value_manager_sy]
    all_list.append(['经营资产收益(息前利润-金融收益-股权收益)']+formatted_row)
    # 经营资产收益率(经营资产收益/经营资产总额)
    tmp_sy = calc_xsbl(value_manager_sy,manager_asset)
    all_list.append(['•经营资产收益率(经营资产收益/经营资产总额)']+tmp_sy)
    # 经营资产收益贡献率
    tmp_gx_lv_jy = calc_gxlv(tmp_bilv,tmp_sy)
    all_list.append(['经营资产收益贡献率']+tmp_gx_lv_jy)
    # -----------
    all_list.append(fen_ge)
    all_list.append(['总本金利用率']+zbj_sylv)
    # 总贡献率(股权贡献+金融贡献+经营贡献)
    tmp_all = calc_gxlv_sum(tmp_gx_lv_gq,tmp_gx_lv_jl)
    tmp_all = calc_gxlv_sum(tmp_all,tmp_gx_lv_jy)
    all_list.append(['∑总贡献率(股权贡献+金融贡献+经营贡献≈息前回报率)']+tmp_all)
    # -----------
    all_list.append(fen_ge)
    
    # 各种效率
    # 总本金周转率、总本金回现率、应收回款天数、存货周转天数
    # 总本金周转率（营业收入/平均总本金)
    value_average_zbj = calc_average_value(sum_all_xianjin) # 平均总本金
    data_zbjzzlv = calc_jxb(value_yysr,value_average_zbj)
    all_list.append(['•资本周转率(营业收入/平均总本金)']+data_zbjzzlv)
    # 主营业务收入 = 营业收入 - 经融资产收入
    # 主营业务本金 =  长期股权资金 + 长期经营资金 + 周转资金
    # 实际主营资金周转率
    value_zysr = get_list_data_subtract(value_yysr,value_jrzc_sy) 
    value_zysr = get_list_data_subtract(value_zysr,value_guquan_sy)
    formatted_zysr=["{:,.2f}".format(num) for num in value_zysr]
    all_list.append(['主营收入(营业收入-金融收入-股权收益)']+formatted_zysr)
    all_list.append(['主营本金(经营总资产)']+formatted_manager)
    value_average_zybenjin = calc_average_value(manager_asset)
    data_zyzzlv = calc_jxb(value_zysr,value_average_zybenjin)
    all_list.append(['主营本金周转率(主营收入/平均主营本金)']+data_zyzzlv)
    all_list.append(formatted_maoli)
    all_list.append(fen_ge)
    
    # 存货周转天数 360/存货周转率=360/(营业成本/平均存货余额)
    data_cunhuo = get_single_data(report_fuzai,'存货')
    value_cunhuo = remove_list_data_douao(data_cunhuo[1:])
    avrage_cunhuo = calc_average_value(value_cunhuo)
    data_cunhuo_zzlv = calc_jxb(value_yycb,avrage_cunhuo)
    # all_list.append(['存货周转率']+data_cunhuo_zzlv)
    tmp_value = ['360.0'] * (i_title_col-1)
    value_cunhuo_zzlv = remove_list_data_douao(data_cunhuo_zzlv)
    data_cunhuo_day = calc_jxb(tmp_value,value_cunhuo_zzlv)
    all_list.append(['•存货周转(天)']+data_cunhuo_day)
    # 存货占比(存货/经营总资产)
    data_cunhuo_bl = calc_xsbl(value_cunhuo,manager_asset)
    all_list.append(['存货占比(存货/经营总资产)']+data_cunhuo_bl)
    
    xs_yishou_kuan = get_single_data(all_list,'销售应收款');
    all_list.append(xs_yishou_kuan)
    value_ys_sum = remove_list_data_douao(xs_yishou_kuan)[1:]
    average_ys = calc_average_value(value_ys_sum)
    data_ys_zzlv = calc_jxb(value_yysr,average_ys) #应收款周转率=营业收入/平均应收账款
    # all_list.append(['应收款周转率']+data_ys_zzlv)
    tmp_value = ['360.0'] * (i_title_col-1)
    value_ys_zzlv = remove_list_data_douao(data_ys_zzlv)
    data_ys_day = calc_jxb(tmp_value,value_ys_zzlv)
    all_list.append(['应收回款(天)']+data_ys_day)
    value_ys_jg  = calc_growing_value(value_ys_sum) #应收增加额
    data_ys_jg= ["{:,.2f}".format(num) for num in value_ys_jg]
    all_list.append(['应收增加额']+data_ys_jg)
    value_jsys = remove_list_data_douao(data_jsys)
    data_ys_bl = calc_xsbl(value_ys_jg,value_jsys)
    all_list.append(['应收占比(应收增加额/营业收入*1.17)']+data_ys_bl) 
    #营业收入×117%≈销售 商品、提供劳务收到的现金+应收账款、应收票据增加额
    data_yushou = get_single_data(all_list,'销售预收款')
    value_yushou = remove_list_data_douao(data_yushou[1:])
    value_yushou_jg  = calc_growing_value(value_yushou) #预收增加额
    data_yushou_jg= ["{:,.2f}".format(num) for num in value_yushou_jg]
    all_list.append(['预收增加额']+data_yushou_jg)
    data_yushou_bl = calc_xsbl(value_yushou_jg,value_jsys)
    all_list.append(['预收占比(预收增加额/营业收入*1.17)']+data_yushou_bl) 
    
    # 应付周转天 = 360/应付周转率 
    # data_yf_kuan = get_single_data(report_fuzai,'应付账款')
    # data_yf_piaoju = get_single_data(report_fuzai,'应付票据')
    # value_yf_kuan = remove_list_data_douao(data_yf_kuan[1:])
    # value_yf_piaoju = remove_list_data_douao(data_yf_piaoju[1:])
    # value_yf_all = get_list_data_sum(value_yf_kuan,value_yf_piaoju)
    # formatted_yf=["{:,.2f}".format(num) for num in value_yf_all]
    # all_list.append(['应付账款(销售应付款)']+formatted_yf)
    xs_yifu_kuan = get_single_data(all_list,'销售应付款');
    all_list.append(xs_yifu_kuan)
    value_yf_all = remove_list_data_douao(xs_yifu_kuan)[1:]
    average_yf = calc_average_value(value_yf_all)
    data_yf_zzlv = calc_jxb(value_yycb,average_yf) # 应付周转率=营业成本/平均应付账款(应付账款+应付票据)
    tmp_value = ['360.0'] * (i_title_col-1)
    value_yf_zzlv = remove_list_data_douao(data_yf_zzlv)
    data_yf_day = calc_jxb(tmp_value,value_yf_zzlv)
    all_list.append(['应付周转(天)']+data_yf_day)
    data_yf_bl = calc_xsbl(value_yf_all,value_yycb)
    all_list.append(['应付占比(应付/营业成本)']+data_yf_bl)
     
    # 现金周转天数=存货周转天数+应收账款周转天数-应付账款拖延天数
    value_ch_ys = get_list_data_sum(remove_list_data_douao(data_cunhuo_day),remove_list_data_douao(data_ys_day))
    value_sub_yf = get_list_data_subtract(value_ch_ys,remove_list_data_douao(data_yf_day))
    formatted_xianjin_day=["{:,.2f}".format(num) for num in value_sub_yf]
    all_list.append(['•现金周转(天)(存货天+应收天-应付天)']+formatted_xianjin_day)
    # -----------
    all_list.append(fen_ge)
    
    # 各种增长率（最好是：成本增长率<营收增长率<净利润增长率）
    tmp_grow_lv = ['•成本增长率'] + calc_grow_lv(value_yycb)
    all_list.append(tmp_grow_lv)
    
    tmp_grow_lv = ['•营收增长率'] + calc_grow_lv(value_yysr)
    all_list.append(tmp_grow_lv)
    
    tmp_grow_lv = ['•净利润增长率'] + calc_grow_lv(value_gm_jlr)
    all_list.append(tmp_grow_lv)
    
    tmp_grow_lv = ['扣非息前利润增长率'] + calc_grow_lv(value_kfxqlr)
    all_list.append(tmp_grow_lv)
    
    tmp_grow_lv = ['总本金增长率'] + calc_grow_lv(sum_all_xianjin)
    all_list.append(tmp_grow_lv)
    
    tmp_grow_lv = ['•归母权益增长率'] + calc_grow_lv(gm_quanyi_value)
    all_list.append(tmp_grow_lv)
    #
    tmp_grow_lv = ['有息债增长率'] + calc_grow_lv(sum_youxi)
    all_list.append(tmp_grow_lv)
    # 
    tmp_grow_lv = ['经营总资产增长率'] + calc_grow_lv(manager_asset)
    all_list.append(tmp_grow_lv)
    
    tmp_grow_lv = ['•长期经营资产增长率'] + calc_grow_lv(sum_long_asset)
    all_list.append(tmp_grow_lv)
    # 
    tmp_grow_lv = ['•金融资产增长率'] + calc_grow_lv(value_jrzc)
    all_list.append(tmp_grow_lv)
    # 
    tmp_grow_lv = ['存货增长率'] + calc_grow_lv(value_cunhuo)
    all_list.append(tmp_grow_lv)
    
    tmp_grow_lv = ['应收款增长率'] + calc_grow_lv(value_ys_sum)
    all_list.append(tmp_grow_lv)
    
    data_yushou_kuan = get_single_data(report_fuzai,'预收款项')
    value_yushou_kuan = remove_list_data_douao(data_yushou_kuan[1:])
    data_ht_kuan = get_single_data(report_fuzai,'合同负债')
    value_ht_kuan = remove_list_data_douao(data_ht_kuan[1:])
    value_yushou_sum = get_list_data_sum(value_yushou_kuan,value_ht_kuan)
    tmp_grow_lv = ['预收款增长率'] + calc_grow_lv(value_yushou_sum)
    all_list.append(tmp_grow_lv)
    # 复合5增长率(净利>营收>成本>长期资产>金融资产>股东权益)
    value_fh_jinli = (float(value_gm_jlr[0]) / float(value_gm_jlr[5])) ** (1 / 5) - 1 if float(value_gm_jlr[0]) > 0 else 0
    data_fh_jinli = f"{value_fh_jinli * 100:.2f}%"
    value_fh_yinshou = (float(value_yysr[0])/float(value_yysr[5])) ** (1/5) - 1
    data_fh_yinshou = f"{value_fh_yinshou * 100:.2f}%"
    value_fh_chengben= (float(value_yycb[0])/float(value_yycb[5])) ** (1/5) - 1
    data_fh_chengben = f"{value_fh_chengben * 100:.2f}%"
    value_fh_cqzc = (float(sum_long_asset[0])/float(sum_long_asset[5])) ** (1/5) - 1
    data_fh_cqzc = f"{value_fh_cqzc * 100:.2f}%"
    value_fh_xjl = (float(value_xjl[0])/float(value_xjl[5])) ** (1/5) - 1 if float(value_xjl[0])>0 else 0
    data_fh_xjl = f"{value_fh_xjl * 100:.2f}%"
    value_fh_gudongqy = (float(value_jrzc[0])/float(value_jrzc[5])) ** (1/5) - 1 if float(value_jrzc[0])>0 else 0
    data_fh_gudongqy = f"{value_fh_gudongqy * 100:.2f}%"
    all_list.append(['•近5年复合增长率(最优：现>净>收>成)','现金流:'+data_fh_xjl,'净利:'+data_fh_jinli,'营收:'+data_fh_yinshou,'成本:'+data_fh_chengben,'固产:'+data_fh_cqzc,'金融:'+data_fh_gudongqy])
    
    # -----------
    all_list.append(fen_ge)
    
     # 自由现金流=现金流+处置收益-战略支出费用
    if len(report_xianjin)>0:
        all_list.append(row_xjll_je)
        # 总本金回现率(现金净额/平均总本金)
        data_zbjhxlv = calc_xsbl(value_xjl,value_average_zbj)
        all_list.append(['•现金流回报率(CFROI=现金净额/平均总本金)']+data_zbjhxlv)
        
        value_zyxj = value_xjl 
        # 处置固定资产,处置子公司,购建固定资产,取得子公司
        data_cz_gc = get_single_data(report_xianjin,'处置固定资产')
        if len(data_cz_gc)>0:
            data_cz_gc = repair_nulldata_2_zero(data_cz_gc)
            all_list.append(data_cz_gc)
            value_cz_gc = remove_list_data_douao(data_cz_gc[1:])
            value_zyxj = get_list_data_sum(value_zyxj,value_cz_gc)
        data_cz_zgs = get_single_data(report_xianjin,'处置子公司')
        if len(data_cz_zgs)>0:
            data_cz_zgs = repair_nulldata_2_zero(data_cz_zgs)
            all_list.append(data_cz_zgs)
            value_cz_zgs = remove_list_data_douao(data_cz_zgs[1:])
            value_zyxj = get_list_data_sum(value_zyxj,value_cz_zgs)
            
        value_ztj = []; #记录总投建
        value_zccxj = value_zyxj #记录总产出现金=现金净额+处置收入    
        data_gj_gc = get_single_data(report_xianjin,'购建固定资产')
        if len(data_gj_gc)>0:
            data_gj_gc = repair_nulldata_2_zero(data_gj_gc)
            all_list.append(data_gj_gc)
            value_gj_gc = remove_list_data_douao(data_gj_gc[1:])
            value_zyxj = get_list_data_subtract(value_zyxj,value_gj_gc)
            value_ztj = value_gj_gc
        data_gj_zgs = get_single_data(report_xianjin,'取得子公司')
        if len(data_gj_zgs)>0:
            data_gj_zgs = repair_nulldata_2_zero(data_gj_zgs)
            all_list.append(data_gj_zgs)
            value_gj_zjs = remove_list_data_douao(data_gj_zgs[1:])
            value_zyxj = get_list_data_subtract(value_zyxj,value_gj_zjs)
            if len(value_ztj)>0:
                value_ztj = get_list_data_sum(value_ztj,value_gj_zjs)
            else:
                value_ztj = value_gj_zjs
            
        formatted_zyxj=["{:,.2f}".format(num) for num in value_zyxj]
        all_list.append(['•自由现金流(现金流+处置-购建)']+formatted_zyxj)
        value_zyxj_deep = get_list_data_subtract(value_zyxj,sum_zz_jtr)
        formatted_zyxj_deep=["{:,.2f}".format(num) for num in value_zyxj_deep]
        all_list.append(['*深度自由现金流(自由现金流-周转净投入)']+formatted_zyxj_deep)
        
        value_gjgc = remove_list_data_douao(data_gj_gc[1:])
        data_ztlv = calc_xsbl(value_gjgc,value_xjl)
        all_list.append(['再投率(购建/现金流)']+data_ztlv)
        
        data_fpgl = get_single_data(report_xianjin,'分配股利')
        all_list.append(['分配股利及偿息']+repair_nulldata_2_zero(data_fpgl[1:]))
        value_fpgl = remove_list_data_douao(data_fpgl[1:])
        value_fpgl_sum = sum(float(x) for x in value_fpgl)
        # 总投建>产出现金>净赚现金>总分红
        if len(value_ztj)>0: 
            ztj_sum = sum(float(x) for x in value_ztj); # 总投建=购建固定资产+取得子公司
            zcc_sum = sum(value_zccxj) #总产出现金=现金净额+处置收入
            jzxj_sum = sum(value_zyxj) #净赚现金即自由现金流汇总
            tmp_sum_list = [ztj_sum,zcc_sum,jzxj_sum,value_fpgl_sum];#总投、总产出现金、净赚现金、总分红
            formatted_sum_list=["{:,.2f}".format(num) for num in tmp_sum_list] 
            #复合收益率 Power(zcc_sum/ztj_sum,1/6)-1
            # 计算复合收益率（总产出现金/总投入现金）的复合收益
            compound_return = (zcc_sum / ztj_sum) ** (1 / 6) - 1
            fhsy_value = f"{compound_return * 100:.2f}%" #
            formatted_sum_list.append('复利6：'+fhsy_value)
            # formatted_sum_list.append('盈再率:') # 盈再率 = (期末长期经营资产-期初长期经营资产)/N年净利总和
            value_cqzc = (sum_long_asset[0]-sum_long_asset[5]) #(期末长期经营资产-期初长期经营资产)
            sum_lirun_5 = sum(float(x) for x in value_gm_jlr[:5]) #近5年的利润总和  
            value_yzlv = f"{(value_cqzc/sum_lirun_5) * 100:.2f}%"  
            formatted_sum_list.append('盈再率5：'+value_yzlv)
            all_list.append(['•总投建>总产出>净赚现金>总分红偿息']+formatted_sum_list)
        
        # 偿息能力(自由现金流-利息费用)
        tmp_value = calc_xsbl(value_zyxj,value_gm_jlr)
        all_list.append(['盈利质量(自由现金流/归母净利润≥80%)']+tmp_value)
        tmp_value = calc_xsbl(value_zyxj,sum_youxi)
        all_list.append(['现金流覆盖(自由现金流/有息负债≥20%)']+tmp_value)
        
        tmp_value = get_list_data_subtract(value_zyxj,value_lxfy)
        formatted_rowdata=["{:,.2f}".format(num) for num in tmp_value]
        all_list.append(['偿息能力(自由现金流-利息费用)']+formatted_rowdata)
        # 偿债能力(金融资产-有息负债)
        tmp_value = get_list_data_subtract(value_jrzc,sum_youxi)
        formatted_rowdata=["{:,.2f}".format(num) for num in tmp_value]
        all_list.append(['偿债能力(金融资产-有息负债)']+formatted_rowdata)
        # 现金分红能力
        value_xjfh = get_list_data_subtract(value_zyxj,value_fpgl)
        formatted_xjfh=["{:,.2f}".format(num) for num in value_xjfh]
        all_list.append(['现金分红偿息能力(自由现金流-分配股利及偿息)']+formatted_xjfh)
        # # 净利润分红能力
        value_lirunfh = get_list_data_subtract(value_gm_jlr,value_fpgl)
        formatted_lirunfh=["{:,.2f}".format(num) for num in value_lirunfh]
        all_list.append(['净利分红偿息能力(净利润-分配股利及偿息)']+formatted_lirunfh)
    # -----------
    all_list.append(fen_ge)
    if report_xianjin_buchong is not None and len(report_xianjin_buchong)>0:
        # 固定资产折旧+使用权资产折旧+无形资产折旧+长期待摊费用摊销
        data_gdzc_zj = get_single_data(report_xianjin_buchong,'固定资产折旧')
        value_gdzc_zj = remove_list_data_douao(data_gdzc_zj[1:])
        all_list.append(data_gdzc_zj);
        
        data_syqzc_zj = get_single_data(report_xianjin_buchong,'使用权资产折旧')
        value_syqzc_zj= remove_list_data_douao(data_syqzc_zj[1:])
        all_list.append(data_syqzc_zj);
        
        data_wxzc_zj = get_single_data(report_xianjin_buchong,'无形资产折旧')
        value_wxzc_zj= remove_list_data_douao(data_wxzc_zj[1:])
        all_list.append(data_wxzc_zj);
        
        data_cqdtfy_zj = get_single_data(report_xianjin_buchong,'长期待摊费用摊销')
        value_cqdtfy_zj = remove_list_data_douao(data_cqdtfy_zj[1:])
        all_list.append(data_cqdtfy_zj);
        
        value_sum_zhejiu = get_list_data_sum(value_gdzc_zj,value_syqzc_zj)
        value_sum_zhejiu = get_list_data_sum(value_sum_zhejiu,value_wxzc_zj)
        value_sum_zhejiu = get_list_data_sum(value_sum_zhejiu,value_cqdtfy_zj)
        formatted_zhejiu_list=["{:,.2f}".format(num) for num in value_sum_zhejiu]
        all_list.append(['∑维持性所需资金(折旧+摊销)']+formatted_zhejiu_list)
        value_gj_gc = remove_list_data_douao(data_gj_gc[1:])
        value_kuozhang = get_list_data_subtract(value_gj_gc,value_sum_zhejiu)
        formatted_zhejiu_list=["{:,.2f}".format(num) for num in value_kuozhang]
        all_list.append(['•扩张性投入资金(购建-维持)']+formatted_zhejiu_list)
        # 现金流净额-维持性所需资金-周转净投入
        value_r = get_list_data_subtract(value_xjl,value_sum_zhejiu)
        formatted_r=["{:,.2f}".format(num) for num in value_r]
        all_list.append(['•现金流维持经营(现金净额-维持资金)']+formatted_r)
        value_r = get_list_data_subtract(value_r,sum_zz_jtr)
        formatted_r=["{:,.2f}".format(num) for num in value_r]
        all_list.append(['•现金流周维余额(现金净额-周转净投入-维持资金)']+formatted_r)
        # 维护盈利无需大量资出投入：也可以简单理解为主营成本，因为主营成本是刚性成本。主营成本不大，也即意味着高毛利，是故毛利低于20%以下的企业，基本不在考虑范围内。
        value_r = get_list_data_subtract(value_xjl,value_yycb)
        formatted_r=["{:,.2f}".format(num) for num in value_r]
        all_list.append(['•现金流维持主营(现金净额-主营成本)']+formatted_r)
        
        # -------------
        all_list.append(fen_ge)
        # 资产减值准备，数额大的要查原因
        data_jzzb = get_single_data(report_xianjin_buchong,'资产减值准备')
        if data_jzzb!=['资产减值准备','0','0','0','0','0','0']:
            all_list.append(['！资产减值准备']+data_jzzb[1:])
            data_jzzb = get_single_data(report_xianjin_buchong,'信用减值损失')
            if data_jzzb!=['信用减值损失','0','0','0','0','0','0']:
                all_list.append(['！信用减值损失']+data_jzzb[1:])
            all_list.append(fen_ge)
    # 股东投入的资金（实收资本+资本公积）
    data_guben = get_single_data(report_fuzai,'股本') #实收资本（股本）
    if data_guben==['股本','0','0','0','0','0','0']:
        data_guben = get_contain_single_data(report_fuzai,'股本','实收资本')
    value_guben = remove_list_data_douao(data_guben[1:])
    all_list.append(data_guben)
    data_zibengj = get_single_data(report_fuzai,'资本公积')
    value_zibengj = remove_list_data_douao(data_zibengj[1:])
    all_list.append(data_zibengj)
    data_yingyugj = get_single_data(report_fuzai,'盈余公积')
    value_yingyugj = remove_list_data_douao(data_yingyugj[1:])
    all_list.append(data_yingyugj)
    data_wfplirun = get_single_data(report_fuzai,'未分配利润')
    value_wfplirun = remove_list_data_douao(data_wfplirun[1:])
    all_list.append(data_wfplirun)
    value_gd_touru = get_list_data_sum(value_guben,value_zibengj)
    value_gd_shouru = get_list_data_sum(value_yingyugj,value_wfplirun)
    value_gd_jingshouru = get_list_data_subtract(value_gd_shouru,value_gd_touru)
    formatted_jingshouru=["{:,.2f}".format(num) for num in value_gd_jingshouru]
    all_list.append(['股东收益(未分配+盈余-股本-资本公积)']+formatted_jingshouru)
    all_list.append(fen_ge)
    # 企业用本金赚回来的钱（盈余公积+未分配利润）
    # 本期未分配利润 = 上期未分配利润 + 本期净利润 - 本期利润分配（提取盈余公积、分配股利等）
    
    # 总本金
    all_list.append(formatted_all_xianjin)
    #筹集资金转化资核对  总本金(股东权益+有息债)=长期股权投资+金融资金+经营资产总额(长期经营资产+周转性净投入总额<经营资产-经营负债>)
    value_hedui_1 = get_list_data_sum(value_guquan,value_jrzc)
    value_hedui_2 = get_list_data_sum(value_hedui_1,manager_asset)
    # 如果有预计负债，还要减掉预计负债，才能相等，因周转性净投入总额那里没有减掉’预计负债‘
    data_yjfz = get_single_data(report_fuzai,'预计负债')
    if data_yjfz!=['预计负债','0','0','0','0','0','0']:
        value_yjfz = remove_list_data_douao(data_yjfz[1:])
        value_hedui_2 = get_list_data_subtract(value_hedui_2,value_yjfz)
    
    formatted_hedui=["{:,.2f}".format(num) for num in value_hedui_2]
    if formatted_hedui == formatted_all_xianjin[1:]:
        formatted_hedui.insert(0,"✔本金转化资产核对(长期股权+金融+经营总额)")
    else:
        formatted_hedui.insert(0,"≠本金转化资产核对(长期股权+金融+经营总额)")
    all_list.append(formatted_hedui)
    
    all_list.append(fen_ge)
    # 老唐估值法,近5年的归母复合增长率及最近一年的增长的最小值，作为未来3年增长率参考，计算得到3年后的市值
    # 先找合适的增长率
    data_zzlv_1= calc_grow_lv(value_gm_jlr)[0] #最近一年归母净利增长率
    percentage_str = data_zzlv_1.rstrip('%')# 去掉百分号
    value_zzlv_1 = float(percentage_str) / 100 # 转换为浮点数并除以 100
    value_zzlv_2 = value_fh_jinli #复合归母净利润
    value_zzlv_3 = value_fh_xjl #复合现金流净额 
    data_zzlv_zyxj = calc_grow_lv(value_zyxj)[0] #最近一年自由现金流增长率
    percentage_zyxj = data_zzlv_zyxj.rstrip('%')
    value_zzlv_4 = float(percentage_zyxj) / 100 
    data_zzlv_xjl = calc_grow_lv(value_xjl)[0] #最近一年现金流净额增长率
    percentage_xjl = data_zzlv_xjl.rstrip('%')
    value_zzlv_5 = float(percentage_xjl) / 100
    value_zzlv_6 = value_fh_yinshou
    value_zzlv_list = [value_zzlv_1,value_zzlv_2,value_zzlv_3,value_zzlv_4,value_zzlv_5,value_zzlv_6]
    # 直接找出大于 0 的最小值，next() 函数用于获取生成器的下一个元素，如果没有符合条件的元素，就返回 None
    value_zzlv = next((i for i in sorted(value_zzlv_list) if i > 0), 0)
    data_zzlv = f"{value_zzlv * 100:.2f}%"
    
    all_list.append(['-','复利:'+data_fh_jinli,'复现:'+data_fh_xjl,'复收:'+data_fh_yinshou,'近净:'+data_zzlv_1,'近现:'+data_zzlv_xjl,'近自由:'+data_zzlv_zyxj])
    all_list.append(['-','-',zong_guben,'-','P20','P25','P30'])
    
    value_3Year = float(value_gm_jlr[0])*((1+value_zzlv)**3) #3年后净利润
    data_3year = "{:,.2f}".format(value_3Year)
    
    value_p20 = value_3Year * 10
    data_p20 = "{:,.2f}".format(value_p20/100000000)
    value_p25 = value_3Year * 12.5
    data_p25 = "{:,.2f}".format(value_p25/100000000)
    value_p30 = value_3Year * 15
    data_p30 = "{:,.2f}".format(value_p30/100000000)
    
    value_p20_max = value_p20 * 3
    data_p20_max = "{:,.2f}".format(value_p20_max/100000000)
    value_p25_max = value_p25 * 3
    data_p25_max = "{:,.2f}".format(value_p25_max/100000000)
    value_p30_max = value_p30 * 3
    data_p30_max = "{:,.2f}".format(value_p30_max/100000000)
    
    data_p20_jia = ''
    data_p25_jia = ''
    data_p30_jia = ''
    data_p20_max_jia = ''
    data_p25_max_jia = ''
    data_p30_max_jia = ''
    if zong_guben>0:
        value_p20_jia = value_p20 / 100000000 / zong_guben
        data_p20_jia = "({:,.2f})".format(value_p20_jia)
        value_p25_jia = value_p25 / 100000000 / zong_guben
        data_p25_jia = "({:,.2f})".format(value_p25_jia)
        value_p30_jia = value_p30 / 100000000 / zong_guben
        data_p30_jia = "({:,.2f})".format(value_p30_jia)
        
        value_p20_max_jia = value_p20_max / 100000000 / zong_guben
        data_p20_max_jia = "({:,.2f})".format(value_p20_max_jia)
        value_p25_max_jia = value_p25_max / 100000000 / zong_guben
        data_p25_max_jia = "({:,.2f})".format(value_p25_max_jia)
        value_p30_max_jia = value_p30_max / 100000000 / zong_guben
        data_p30_max_jia = "({:,.2f})".format(value_p30_max_jia)
    
    # 1、理想买点：三年后合理估值的50%为目前的理想买点，如果三年后合理估值是1000亿，那么当前500亿市值是理想买点。
    # 2、理想卖点：三年后合理估值的150%或当年50倍动态市盈得，二者中的较低值为一年内卖点。
    all_list.append(['老唐估值(归母净利润)',data_gm_jlr[1],data_zzlv,data_3year,data_p20+data_p20_jia,data_p25+data_p25_jia,data_p30+data_p30_jia])
    all_list.append(['-','-','-','-',data_p20_max+data_p20_max_jia,data_p25_max+data_p25_max_jia,data_p30_max+data_p30_max_jia])
    # 归母净利润、增长率、3年后净利润、20倍市值、25倍市值、30倍市值
    
    value_3Year_xj = float(value_zyxj[0])*((1+value_zzlv)**3) #3年后的自由现金流
    data_3year_xj = "{:,.2f}".format(value_3Year_xj)
    
    value_p20_xj = value_3Year_xj * 10
    data_p20_xj = "{:,.2f}".format(value_p20_xj/100000000)
    value_p25_xj = value_3Year_xj * 12.5
    data_p25_xj = "{:,.2f}".format(value_p25_xj/100000000)
    value_p30_xj = value_3Year_xj * 15
    data_p30_xj = "{:,.2f}".format(value_p30_xj/100000000)
    
    value_p20_max_xj = value_p20_xj * 3
    data_p20_max_xj = "{:,.2f}".format(value_p20_max_xj/100000000)
    value_p25_max_xj = value_p25_xj * 3
    data_p25_max_xj = "{:,.2f}".format(value_p25_max_xj/100000000)
    value_p30_max_xj = value_p30_xj * 3
    data_p30_max_xj = "{:,.2f}".format(value_p30_max_xj/100000000)
    
    data_p20_jia = ''
    data_p25_jia = ''
    data_p30_jia = ''
    data_p20_max_jia = ''
    data_p25_max_jia = ''
    data_p30_max_jia = ''
    if zong_guben>0:
        value_p20_jia = value_p20_xj / 100000000 / zong_guben
        data_p20_jia = "({:,.2f})".format(value_p20_jia)
        value_p25_jia = value_p25_xj / 100000000 / zong_guben
        data_p25_jia = "({:,.2f})".format(value_p25_jia)
        value_p30_jia = value_p30_xj / 100000000 / zong_guben
        data_p30_jia = "({:,.2f})".format(value_p30_jia)
        
        value_p20_max_jia = value_p20_max_xj / 100000000 / zong_guben
        data_p20_max_jia = "({:,.2f})".format(value_p20_max_jia)
        value_p25_max_jia = value_p25_max_xj / 100000000 / zong_guben
        data_p25_max_jia = "({:,.2f})".format(value_p25_max_jia)
        value_p30_max_jia = value_p30_max_xj / 100000000 / zong_guben
        data_p30_max_jia = "({:,.2f})".format(value_p30_max_jia)
    
    all_list.append(['老唐估值(自由现金流)',formatted_zyxj[0],data_zzlv,data_3year_xj,data_p20_xj+data_p20_jia,data_p25_xj+data_p25_jia,data_p30_xj+data_p30_jia])
    all_list.append(['-','-','-','-',data_p20_max_xj+data_p20_max_jia,data_p25_max_xj+data_p25_max_jia,data_p30_max_xj+data_p30_max_jia])
        
    # 现金流量表（现金流量净额、处置固产、处置子公司、购置投资、购买子公司)
    # 战略支出支付费用 = 购置投资 + 购买子公司
    # 回收后所需支出 = 战略支出支付费用 - 处置固产 - 处置子公司
    # 现金流量补充表
    # 维持支出 = 资产减值 + 固定资产折旧 + 使用权资产折旧 + 无形摊销 + 长期待摊摊销
    # 扩张支出 = 战略支出支付费用 - 保本支出
    # 现金覆盖： 现金流 / 回收后所需支出, 现金流 / 维持支出, 
    # 自由现金流 = 现金流量 -  回收后所需支出 - 利息费用
    
    print_row_data(all_list)

    if len(filepath)>0:
        save_data_2_number(all_list,filepath)
    